Information Disclosure in Flask with Basic Auth
Information Disclosure in Flask with Basic Auth — how this specific combination creates or exposes the vulnerability
Flask’s minimal defaults and the use of HTTP Basic Authentication can unintentionally expose sensitive information when error handling, logging, or transport protections are incomplete. Basic Auth encodes credentials with Base64, which is reversible and not encryption; if a response inadvertently includes credentials, logs, or debug data, an attacker can recover them.
In a Flask app using flask_httpauth or a custom Authorization header check, information disclosure can occur through several channels:
- Debug tracebacks: When
DEBUG=True, detailed error pages may echo request headers, including theAuthorizationheader, revealing usernames and Base64-encoded credentials to an unauthenticated attacker. - Server or application logs: If headers are logged verbatim, Base64-encoded credentials are stored in plaintext logs, creating a retrievable credential store for anyone with log access.
- HTTP method leakage via OPTIONS/redirects: Misconfigured CORS or redirect behavior can cause the browser to send an
Authorizationheader to an origin that does not require credentials, exposing credentials to a different endpoint. - Inadequate transport protection: Without TLS, intercepted requests expose the Base64 string, enabling replay even if credentials are rotated.
- Response content references: Error messages or hypermedia that include resource identifiers derived from authenticated user data can disclose relationships or sensitive business logic when combined with a known username.
middleBrick’s unauthenticated scan checks for these patterns by analyzing runtime behavior, OpenAPI/Swagger definitions with full $ref resolution, and header flows. Among its 12 security checks, Data Exposure and Authentication are evaluated in parallel to detect whether credentials appear in responses, logs, or error payloads, and whether transport is properly enforced. In LLM/AI Security, system prompt leakage patterns and active prompt injection probes ensure that AI endpoints do not disclose credentials or administrative instructions through generated text or tool calls. The scanner outputs a letter-grade risk assessment and prioritized findings with remediation guidance, helping teams identify and mitigate information disclosure without requiring agent installation or credentials.
Basic Auth-Specific Remediation in Flask — concrete code fixes
Secure Flask applications using Basic Auth should disable debug in production, avoid logging headers, enforce TLS, and validate redirect targets. Below are concrete, minimal examples that reduce information disclosure risk.
1. Safe Basic Auth setup with flask_httpauth
This example uses flask_httpauth.HTTPBasicAuth with a verified user callback and disables debug mode.
from flask import Flask, jsonify
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
auth = HTTPBasicAuth()
# In production, use a secure user store with hashed credentials
USERS = {
"alice": "s3cr3tP@ssw0rd", # Example: store only hashed passwords in real use
}
@auth.verify_password
def verify_password(username, password):
if username in USERS and USERS[username] == password: # Replace with hashed check
return username
return None
@app.route("/api/me")
@auth.login_required
def me():
return jsonify({ "user": auth.current_user() })
if __name__ == "__main__":
# Never run with debug=True in production
app.run(debug=False, host="0.0.0.0", port=5000)
2. Avoid logging sensitive headers
Ensure request logging does not include the Authorization header. Use a filtered logger instead.
import logging
from flask import request
# Configure a logger that excludes Authorization
class FilterSensitive(logging.Filter):
def filter(self, record):
if hasattr(record, "msg"):
record.msg = str(record.msg).replace(request.headers.get("Authorization", ""), "[REDACTED]")
return True
logger = logging.getLogger("api")
logger.addFilter(FilterSensitive())
@app.before_request
def log_request_info():
logger.info("Headers: %s", dict(request.headers))
3. Enforce TLS and validate redirects
Redirects should not forward credentials to non-HTTPS origins. Validate target URLs before redirecting.
from urllib.parse import urlparse
ALLOWED_HOSTS = { "api.example.com", "app.example.com" }
@app.route("/redirect")
def safe_redirect():
target = request.args.get("url", "")
parsed = urlparse(target)
if parsed.netloc not in ALLOWED_HOSTS or not target.startswith("https://"):
return jsonify({ "error": "Invalid redirect" }), 400
# Use a library like requests for safe client-side redirects instead
return jsonify({ "redirect": target })
4. Disable debug and configure error handlers
Custom error handlers prevent debug tracebacks from leaking headers.
@app.errorhandler(500)
def handle_500(e):
return jsonify({ "error": "Internal server error" }), 500
@app.errorhandler(401)
def handle_401(e):
return jsonify({ "error": "Unauthorized" }), 401
By combining these practices—strong transport enforcement, careful logging, and controlled error handling—teams reduce the likelihood that Basic Auth credentials are disclosed through common application channels.