Symlink Attack in Flask with Api Keys
Symlink Attack in Flask with Api Keys — how this specific combination creates or exposes the vulnerability
A symlink attack in a Flask application that uses API keys can occur when user-influenced paths are used to serve files that contain API keys or are used to locate key material. If an endpoint accepts a filename or directory path and passes it to Flask utilities such as send_file or constructs filesystem paths with string concatenation or os.path.join, an attacker may traverse directories or replace intended files with symbolic links. This can expose API keys stored on disk or cause the application to serve key material to unauthorized clients.
Consider a Flask route that serves configuration files based on a user-supplied name:
import os
from flask import Flask, send_file
app = Flask(__name__)
BASE = 'configs'
@app.route('/download')
def download_config():
name = request.args.get('name', '')
path = os.path.join(BASE, name + '.json')
return send_file(path)
If name is not strictly validated, an attacker can provide a value such as ../../../etc/api_keys or use ../../ sequences to traverse outside the intended directory. If the process has permissions to read files containing API keys, this traversal can lead to key disclosure. Even without traversal, an attacker who can control the filesystem (for example, by having write access to a parent directory used by the app) can create a symbolic link in a location the application trusts. When the application later constructs a path and writes or reads a file, it may follow the symlink and read or overwrite sensitive files that include API keys.
In a black-box scan, middleBrick tests for path traversal and directory traversal by sending sequences like ..%2F and checks whether the application follows symlinks to sensitive locations. Because the scan is unauthenticated and focuses on the exposed attack surface, it can identify whether endpoints that handle API keys are vulnerable to unauthorized access via filesystem manipulation. This is especially important when API keys are stored on disk rather than injected via environment variables at runtime.
Another relevant risk involves endpoints that generate or reference temporary files containing API keys. If an attacker can influence the temporary file path through directory traversal or symlink manipulation, they may redirect writes or reads to a location under attacker control, leading to key exfiltration or code execution when the keys are later used by other services.
Api Keys-Specific Remediation in Flask — concrete code fixes
To mitigate symlink risks when serving or handling API keys in Flask, avoid using user input to build filesystem paths. Instead, use strict allowlists and resolve paths to ensure they remain within a safe directory.
Use os.path.realpath and validate that the resolved path starts with the expected absolute base directory. Do not rely on client-supplied paths for selecting key files.
import os
from flask import Flask, send_file, abort
app = Flask(__name__)
BASE = os.path.abspath('configs')
@app.route('/download')
def download_config():
name = request.args.get('name', '')
if not name.isalnum():
abort(400, 'Invalid name')
path = os.path.realpath(os.path.join(BASE, name + '.json'))
if not path.startswith(BASE):
abort(403, 'Path traversal detected')
return send_file(path)
When API keys must be stored on disk, ensure file permissions restrict read access to the application process only and avoid placing key files in directories that are writable by untrusted users. Prefer environment variables or a secrets manager to inject keys at runtime, which eliminates the need to serve key files via HTTP endpoints.
If you must serve configuration, return the data directly from a controlled source rather than allowing filesystem access. For example:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/config')
def get_config():
# Load from environment or a secure source at runtime
api_key = os.environ.get('API_KEY')
if api_key is None:
abort(500, 'Configuration error')
return jsonify({'api_key': api_key})
For development and CI/CD integration, the middleBrick CLI can be used to scan endpoints that handle API keys and detect path traversal or symlink-related issues. Run middlebrick scan <url> to perform an unauthenticated assessment of the attack surface. Teams using the Pro plan can enable continuous monitoring to detect regressions, and the GitHub Action can fail builds if a scan on staging APIs detects findings related to authentication or data exposure.