flask 3.1.3

Flask Security Blueprint

Approximately 1,005 tokens

Security posture

When developing with Flask, engineers must assume responsibility for securing all application inputs, session lifecycles, and state transitions, as the framework provides core routing and request handling without automatic protection against common vulnerabilities. Security-sensitive surfaces include authentication flows, blueprint routing boundaries, error responses, configuration loading, and file uploads. Developers must ensure that security assumptions fail closed by explicitly validating all incoming payloads, enforcing resource ownership, and hardening deployment boundaries.

Essential implementation rules

  1. Enforce Resource Ownership Checks

Verify that the authenticated user matches the resource owner before permitting any state modifications. Query the database for the target resource and use abort(404) if the resource is missing or abort(403) if unauthorized to prevent Insecure Direct Object Reference vulnerabilities.

  1. Configure Production Error Handling and Exception Behavior

Disable DEBUG, PROPAGATE_EXCEPTIONS, TRAP_BAD_REQUEST_ERRORS, and TRAP_HTTP_EXCEPTIONS in production. Register explicit error handlers to log unhandled exceptions internally while returning sanitized responses without stack traces.

  1. Preserve Request Context in Background Tasks

Decorate functions dispatched to background threads or greenlets with @flask.copy_current_request_context so request and session remain safely accessible without raising runtime errors.

  1. Secure Routing and Blueprint Registration

Specify explicit uppercase HTTP methods for routes, position @app.route as the outermost decorator, configure explicit URL prefixes for blueprints, use parameter converters like int or uuid, and set TRUSTED_HOSTS.

  1. Validate Authentication Inputs

Check incoming username and password inputs on the server side to ensure they are present before querying databases or executing authentication routines.

  1. Implement Secure WSGI Middleware and Context Boundaries

Isolate application components using DispatcherMiddleware, unwrap thread-local proxies via _get_current_object() across thread boundaries, validate HTTP_HOST headers, and wrap app.wsgi_app with ProxyFix when behind a trusted reverse proxy.

  1. Respect Environment Variable Precedence for Configurations

Rely on process environment variables for critical runtime secrets and configuration values. Ensure load_dotenv() does not overwrite existing variables in os.environ.

  1. Hash and Verify Passwords Securely

Use Werkzeug’s generate_password_hash to hash user passwords prior to storage and check_password_hash during login credential validation.

  1. Implement CSRF Protection and SameSite Cookie Policies

Manually validate anti-CSRF tokens on state-changing requests like POST. Configure SESSION_COOKIE_SAMESITE to Lax or Strict and set SESSION_COOKIE_SECURE and SESSION_COOKIE_HTTPONLY to true.

  1. Disable Debug Mode and Development Server in Production

Never enable debug mode or run the built-in development server in production environments. Deploy applications exclusively using dedicated production WSGI servers such as Gunicorn.

  1. Restrict Jinja Safe Filter and Escape Untrusted Output

Apply the Jinja |safe filter exclusively to trusted HTML generated by WTForms field widgets. Explicitly escape untrusted user input using markupsafe.escape() or rely on Jinja’s automatic escaping, and use |tojson for embedded JavaScript.

  1. Sanitize Filenames and Use Directory-Restricted File Serving

Sanitize untrusted filenames using werkzeug.utils.secure_filename before writing files to disk. Use send_from_directory instead of send_file to serve user-requested files safely within a designated base folder.

  1. Use Parameterized Queries for Database Interactions

Pass dynamic parameters separately from SQL statements using placeholders like ? or named parameters to prevent SQL injection vulnerabilities.

  1. Validate Form Data Against Explicit Input Constraints

Bind HTTP request data to form validation classes and execute validation methods like form.validate() before processing submitted payloads in business logic or database operations.

  1. Configure Security Headers and Response Protocols

Set HTTP security headers such as Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, and X-Frame-Options on outgoing responses or via after_request hooks, and ensure Vary: Cookie is set when session data is accessed.

  1. Configure Request Size Limits and Resource Thresholds

Restrict total payload size globally or per-request using MAX_CONTENT_LENGTH or Request.max_content_length, and configure MAX_FORM_MEMORY_SIZE and MAX_FORM_PARTS to prevent resource exhaustion.

  1. Manage Secure Sessions and State Lifecycles

Call session.clear() before writing authentication identifiers during login and entirely upon logout. Define PERMANENT_SESSION_LIFETIME and set session.modified = True when updating nested mutable structures.

Esc