Path Traversal in Flask with Api Keys
Path Traversal in Flask with Api Keys — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when user-controlled input is used to construct file system paths without proper validation, allowing an attacker to access or overwrite files outside the intended directory. In Flask applications that rely on API keys for access control, this risk can be amplified if key handling and file operations are intertwined without careful design.
Consider a Flask endpoint that serves files from a directory based on an API key provided in a request header. If the API key is used to derive a directory path or to authorize access to a file path without validating the resulting path, an attacker can supply crafted input (e.g., ../../../etc/passwd) to traverse directories. Even when authentication is enforced via an API key, server-side logic may mistakenly trust the key to isolate file access, while the underlying path construction remains unsafe.
A common anti-pattern is to embed the API key in a file path or to use it as a lookup key for a storage location without canonicalizing the final path. For example, if an API key maps to a user-specific folder, but the code concatenates user-supplied filenames directly, an attacker who knows or guesses a valid API key can traverse outside their assigned directory. This violates the principle that authorization checks must be coupled with strict input validation and path sanitization, not treated as a substitute for it.
Because middleBrick scans the unauthenticated attack surface, it can detect endpoints where path traversal is possible even when API key authentication appears to be in place. The tool tests inputs such as filename query parameters or body fields with traversal sequences and examines whether the server returns sensitive files or reveals path information. Findings include insecure direct object references and missing path canonicalization, mapped to the BOLA/IDOR and Input Validation checks in the scan.
Real-world examples from reported incidents show that frameworks like Flask do not automatically protect against these issues. Attack patterns such as directory traversal via open() or send_file() are common when developers assume that access control at the API key level is sufficient. middleBrick’s checks for Data Exposure and Property Authorization help highlight these gaps by correlating runtime behavior with spec definitions that may describe file-serving routes without clarifying safe path handling.
To understand the scope, middleBrick compares the OpenAPI specification against runtime behavior. If the spec defines a parameter as a path or file identifier but does not enforce strict pattern constraints, and the implementation uses insecure joins or incomplete sanitization, the scan will flag the endpoint. This enables developers to see how API key usage interacts with file operations and where additional controls are required.
Api Keys-Specific Remediation in Flask — concrete code fixes
Securing Flask endpoints that use API keys requires combining robust authentication with strict path handling. Below are concrete remediation steps and code examples that address path traversal risks specifically in the context of API key usage.
First, always validate and sanitize user input before using it in file operations. Do not rely on API keys to implicitly isolate file paths. Use a whitelist of allowed characters for filenames and reject any input containing path separators or traversal sequences.
from flask import Flask, request, abort
import os
app = Flask(__name__)
# A simple, safe file-serving helper
def safe_join(base, filename):
# Remove any dangerous constructs
filename = os.path.basename(filename)
return os.path.join(base, filename)
@app.route('/files')
def get_file():
api_key = request.headers.get('x-api-key')
if not api_key or api_key != os.getenv('EXPECTED_API_KEY'):
abort(401, 'Invalid API key')
filename = request.args.get('filename', '')
base_dir = '/srv/app/files'
safe_path = safe_join(base_dir, filename)
# Ensure the resolved path stays within base_dir
if not safe_path.startswith(os.path.abspath(base_dir)):
abort(403, 'Path traversal attempt detected')
if not os.path.isfile(safe_path):
abort(404, 'File not found')
return send_file(safe_path)
This approach separates authentication (API key validation) from authorization (path validation). The safe_join function uses os.path.basename to strip directory components, and an explicit prefix check ensures the final path cannot escape the intended directory. This pattern mitigates risks even if the API key is valid but the filename is malicious.
For more complex scenarios, such as serving files tied to API key owners, use a mapping from API key to a directory path and resolve filenames relative to that directory with canonicalization.
import os
from flask import Flask, request, abort
app = Flask(__name__)
# Mapping from API key to allowed base directory (in practice, use a secure store)
API_KEY_BASE = {
'key_a': '/data/owner_a',
'key_b': '/data/owner_b',
}
def resolve_path(api_key, filename):
base = API_KEY_BASE.get(api_key)
if not base:
return None
# Normalize and resolve without symlinks
full = os.path.normpath(os.path.join(base, filename))
if not full.startswith(os.path.abspath(base)):
return None
return full
@app.route('/secure/files')
def secure_file():
api_key = request.headers.get('x-api-key')
filename = request.args.get('name', '')
path = resolve_path(api_key, filename)
if path is None or not os.path.isfile(path):
abort(403, 'Access denied')
return send_file(path)
In this example, the API key selects a base directory, and the filename is joined and normalized. The prefix check prevents escaping the owner’s directory. middleBrick’s scans can verify that such safeguards are present by testing endpoints with traversal payloads and inspecting responses for sensitive data or errors that indicate insecure handling.
Additionally, avoid logging or exposing detailed error messages that could aid path traversal reconnaissance. Use generic error responses and ensure that file operations do not reveal stack traces or filesystem details.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |