Null Pointer Dereference in Flask with Bearer Tokens
Null Pointer Dereference in Flask with Bearer Tokens — how this specific combination creates or exposes the vulnerability
A null pointer dereference in a Flask API using Bearer tokens occurs when code attempts to access a property or method on an object that is None because the token was absent, malformed, or failed authentication. This can expose internal errors, crash request handling, or leak stack traces that aid attackers.
In Flask, Bearer tokens are typically extracted from the Authorization header. If the token is missing or does not follow the Bearer <token> format, a helper that parses the header may return None. Subsequent code that assumes a non-null result—such as calling .decode(), accessing .payload, or passing the value to a validation function—can raise an unhandled exception. In a black-box scan, middleBrick tests this attack surface by sending requests with missing, malformed, and valid Bearer tokens to identify endpoints where missing checks lead to null dereferences.
Consider an endpoint that retrieves a token and immediately uses it without a null check:
from flask import Flask, request, jsonify
def get_token_auth_header():
auth = request.headers.get("Authorization", None)
if auth is None:
return None
parts = auth.split()
if parts[0].lower() != "bearer" or len(parts) != 2:
return None
return parts[1]
app = Flask(__name__)
@app.route("/user")
def get_user():
token = get_token_auth_header()
# Potential null pointer dereference if token is None
decoded = token.split(".")[1] # None has no attribute split
return jsonify({"token_section": decoded})
If no Authorization header is provided, get_token_auth_header returns None. The next line calls token.split(".")[1], which is a null pointer dereference. In a runtime environment, this raises an unhandled exception, causing a 500 error. MiddleBrick’s checks for Authentication and Input Validation surface such risky patterns by probing endpoints with missing and malformed tokens.
Another scenario involves a decorated accessor that returns None on failure and is used directly in business logic:
import jwt
from flask import Flask, request, jsonify
app = Flask(__name__)
def require_token(f):
def wrapper():
token = request.headers.get("Authorization", "").replace("Bearer ", "")
# If token is missing, decoded may be None
decoded = jwt.decode(token, options={"verify_signature": False}) if token else None
# Risk: passing None to a function expecting a dict
user_id = decoded["sub"] # Potential null pointer dereference
return f(user_id)
return wrapper
@app.route("/profile")
@require_token
def profile():
return jsonify({"ok": True})
Here, if the token is absent, decoded is None, and accessing decoded["sub"] causes a null pointer dereference. middleBrick’s checks for Property Authorization and BOLA/IDOR validate whether authorization logic robustly handles absent tokens and enforces proper checks before object access.
These examples illustrate how the combination of Flask routing and Bearer token handling can introduce null pointer dereferences when token presence and format are not rigorously enforced. By testing unauthenticated attack surfaces with various token states, middleBrick identifies such patterns and provides findings with severity, impact context, and remediation guidance aligned with OWASP API Top 10 and related compliance frameworks.
Bearer Tokens-Specific Remediation in Flask — concrete code fixes
Remediation centers on validating the presence and format of the Bearer token before any operations on its components. Always check for None and enforce structure before accessing indexes or decoding.
Safe pattern with explicit null checks and early returns:
from flask import Flask, request, jsonify
app = Flask(__name__)
def get_token_auth_header():
auth = request.headers.get("Authorization", None)
if auth is None:
return None
parts = auth.split()
if parts[0].lower() != "bearer" or len(parts) != 2:
return None
return parts[1]
@app.route("/user")
def get_user():
token = get_token_auth_header()
if token is None:
return jsonify({"error": "Unauthorized"}), 401
# Safe: token is guaranteed to be a non-empty string
segments = token.split(".")
if len(segments) < 2:
return jsonify({"error": "Invalid token format"}), 400
decoded_section = segments[1]
return jsonify({"token_section": decoded_section})
This ensures that missing or malformed tokens result in a controlled 401/400 response rather than a null pointer dereference. For JWT-based workflows, perform a conditional decode only when the token string exists:
import jwt
from flask import Flask, request, jsonify
app = Flask(__name__)
def get_token_auth_header():
auth = request.headers.get("Authorization", None)
if auth is None:
return None
parts = auth.split()
if parts[0].lower() != "bearer" or len(parts) != 2:
return None
return parts[1]
@app.route("/profile")
def profile():
token = get_token_auth_header()
if token is None:
return jsonify({"error": "Unauthorized"}), 401
try:
# Safe: token is a non-empty string
decoded = jwt.decode(token, options={"verify_signature": False})
except Exception:
return jsonify({"error": "Invalid token"}), 400
user_id = decoded.get("sub")
if user_id is None:
return jsonify({"error": "Token missing subject"}), 400
return jsonify({"user_id": user_id})
Defensive programming practices include:
- Returning None early from helper functions when headers are malformed.
- Validating token structure (e.g., two dot-separated segments for JWTs) before indexing.
- Using .get() on decoded payloads to avoid key errors.
- Wrapping decode calls in try/except to handle format issues gracefully.
middleBrick’s CLI can be used to validate these patterns by scanning your endpoint with and without tokens; the GitHub Action can enforce a minimum score threshold in CI/CD, and the Web Dashboard tracks changes over time. The MCP Server allows you to run on-demand scans directly from AI coding assistants to catch null pointer risks before deployment.