Skip to content

presidio-v/presidio-hardened-flask

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

presidio-hardened-flask

CI CodeQL Python 3.9+ License: MIT

A hardened drop-in replacement for Flask that automatically applies production-grade security defaults. Change one import line and your existing Flask app gets security headers, rate limiting, CSRF protection, secret redaction, input sanitization, and more.

Quick Start

Install

pip install presidio-hardened-flask

Usage — Change One Import

Before (plain Flask):

from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello, world!"

After (presidio-hardened-flask):

from presidio_flask import Flask, jsonify, request

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello, secure world!"

That's it. Your app now automatically receives:

Feature What It Does
Security Headers CSP, HSTS, X-Frame-Options, Permissions-Policy, and more on every response
Rate Limiting 60 req/min per IP with exponential backoff (configurable)
CSRF Protection Sec-Fetch-Site aware + token-based fallback for mutating requests
Secret Redaction Passwords, API keys, and tokens are redacted in logs
Session Hardening Secure, HttpOnly, SameSite=Lax cookies by default
Input Sanitization Blocks SQL injection, XSS, and path traversal attempts
CVE Quick-Check Warns at startup if key dependencies have known vulnerabilities
Security Logging Structured Presidio event logging for all requests

Side-by-Side Comparison

Security Headers

Plain Flask returns no security headers by default:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

presidio-hardened-flask adds them automatically:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Permissions-Policy: geolocation=(), camera=(), microphone=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin

Rate Limiting

Plain Flask has no built-in rate limiting. A single client can hammer your API.

presidio-hardened-flask enforces per-IP rate limits with informative headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

When exceeded, returns 429 Too Many Requests with exponential backoff.

Secret Redaction

Plain Flask will happily log passwords and tokens in plain text:

app.logger.info("Request: %s", request.json)
# {"username": "alice", "password": "hunter2", "api_key": "sk-live-abc123"}

presidio-hardened-flask automatically redacts sensitive fields:

from presidio_flask import redact_dict
print(redact_dict({"password": "hunter2", "api_key": "sk-123"}))
# {"password": "***REDACTED***", "api_key": "***REDACTED***"}

CSRF Protection

Plain Flask has no CSRF protection.

presidio-hardened-flask uses a modern two-layer approach:

  1. Sec-Fetch-Site header — blocks cross-origin mutating requests automatically
  2. Token-based fallback — for older browsers or custom setups
from presidio_flask import generate_csrf_token

# In your template / API response:
token = generate_csrf_token()
# Include as X-CSRF-Token header or _csrf_token form field

Configuration

All features are enabled by default but fully configurable:

app = Flask(__name__)
app.config.update(
    # Rate limiting
    PRESIDIO_RATE_LIMIT=100,           # requests per window (default: 60)
    PRESIDIO_RATE_WINDOW=120,          # window in seconds (default: 60)
    PRESIDIO_RATE_LIMIT_ENABLED=True,  # disable entirely if False

    # CSRF
    PRESIDIO_CSRF_ENABLED=True,

    # Input sanitization
    PRESIDIO_SANITIZE_ENABLED=True,

    # Secret redaction
    PRESIDIO_REDACTION_ENABLED=True,

    # Security logging
    PRESIDIO_LOGGING_ENABLED=True,

    # CVE check on startup
    PRESIDIO_CVE_CHECK=True,

    # Custom security headers (merge with/override defaults)
    PRESIDIO_SECURITY_HEADERS={
        "X-Frame-Options": "SAMEORIGIN",
        "Content-Security-Policy": "default-src 'self'; img-src *",
    },
)

Development

# Clone and install
git clone https://github.com/presidio-security/presidio-hardened-flask.git
cd presidio-hardened-flask
uv venv .venv && source .venv/bin/activate
uv pip install -e ".[dev]"

# Run tests
pytest --cov=presidio_flask

# Lint and format
ruff format .
ruff check . --fix

License

MIT

About

Presidio security-hardened enhancements and defaults for Flask applications

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages