Auditing session key storage and signing

Flask uses client-side signed session cookies by default. The session data is serialized and signed using the application's SECRET_KEY.

If your SECRET_KEY is guessable, weak, or exposed in a public repository, attackers can decrypt the cookie, modify the session parameters (such as changing the user ID), sign it with the key, and send it back to impersonate any user.

During a security audit, we check if the key is loaded from secure environment variables. We also use brute-force utilities like flask-unsign to test the strength of the session key.

Pentest finding

Weak Flask secret key leads to administrator access

During an audit of a corporate portal, we downloaded the session cookie. We ran flask-unsign with a standard wordlist and recovered the key: "development-secret". We then forged a new session payload containing administrative privileges and gained full database access.

Raw SQL Injection in Flask endpoints

While Object-Relational Mappers (ORMs) like SQLAlchemy prevent database injections, developers often write raw SQL strings to process custom requests. If user input is concatenated directly into these strings, SQL injection occurs:

# VULNERABLE: Direct string concatenation
query = f"SELECT * FROM transactions WHERE user_id = '{user_input}'"
db.engine.execute(query)

# SECURE: Using parameterized queries
query = "SELECT * FROM transactions WHERE user_id = :user_id"
db.session.execute(text(query), {'user_id': user_input})

Testing route-level authorization and CORS

Flask does not enforce access controls on routes unless decorators like @login_required are explicitly applied. We check all routes to identify endpoints that lack session verification.

We also check Flask-CORS configurations. If the backend accepts requests from any origin (*) and allows credentials (like cookies or Authorization headers), malicious websites can make calls on behalf of authenticated users.

Flask API Security Checklist

If you are running a Flask API, apply these controls immediately:

  1. Set a strong SECRET_KEY: Generate a cryptographically secure key (e.g., using secrets.token_hex(32)) and load it from environment variables.
  2. Use parameter bindings: Never concatenate string inputs inside database queries. Use ORM operations or bound variables.
  3. Apply explicit decorators: Use authentication middleware decorators on all routes that should not be public.

Let Simpa Labs audit your Flask API

We perform manual penetration testing of Python backends and microservices. We will review your routing configurations, check your database interfaces, and test your authentication endpoints.

Book a Flask Pentest