Zip Slip in Flask with Api Keys
Zip Slip in Flask with Api Keys — how this specific combination creates or exposes the vulnerability
Zip Slip is a path traversal vulnerability that occurs when an application constructs file paths using user-supplied input without proper validation. In Flask, this commonly arises when extracting archives (for example, uploaded ZIP files) and using entries directly to build filesystem paths. When API keys are involved, the interaction can become especially risky because keys may be embedded in archive contents, logs, or configuration files extracted from an archive.
Consider a Flask endpoint that accepts a ZIP file containing configuration and API key material. If the server uses the entry names from the archive to build destination paths, an attacker can supply crafted filenames such as ../../../etc/api_keys.json or ../../app/config/secrets.yaml. During extraction, the path traverses outside the intended directory, potentially overwriting critical files or exposing sensitive data. Because API keys are high-value secrets, extracting and writing them to an unsafe location can lead to unintended disclosure or modification.
In the context of middleBrick’s checks, this behavior would be flagged under Input Validation and Data Exposure. The scan tests unauthenticated surfaces and examines how user-controlled data influences file system operations. If an archive entry leads to writing API key files outside a controlled directory, the scan highlights the risk of data exposure and insecure handling of sensitive artifacts. Even when API keys are stored in environment variables or secret managers, extracting an archive that references those paths can inadvertently alter or expose references used by the application.
Additionally, malicious archives can include deeply nested paths designed to exhaust system resources or overwrite files critical to the runtime environment. If Flask processes these archives during deployment or configuration loading, the impact can extend beyond data exposure to service disruption. Because middleBrick’s scan runs in 5–15 seconds and tests the unauthenticated attack surface, it can surface these path traversal risks without requiring credentials.
To understand the exposure, correlate findings with frameworks such as OWASP API Top 10 and standards like PCI-DSS, which emphasize protection of sensitive data such as API keys. A Zip Slip in the file extraction flow can violate these requirements by allowing unauthorized access or modification of key-bearing files. The scanner’s cross-referencing of OpenAPI specs with runtime behavior helps identify mismatches between declared security expectations and actual implementation when archives and key material intersect.
Api Keys-Specific Remediation in Flask — concrete code fixes
Remediation centers on strict path sanitization and isolation of extracted content. Never trust entry names from archives. In Flask, validate and normalize paths, and ensure extracted files remain confined to a designated directory. Below are concrete examples that demonstrate secure handling when API keys are part of the workflow.
Secure ZIP extraction with path validation
Use os.path.normpath and os.path.commonpath to enforce a base directory boundary. This example shows how to safely extract a ZIP while protecting any API key–related files from traversal.
import os
import zipfile
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/upload-config', methods=['POST'])
def upload_config():
if 'archive' not in request.files:
return jsonify({'error': 'No archive provided'}), 400
file = request.files['archive']
base_dir = os.path.abspath('configs')
with zipfile.ZipFile(file.stream, 'r') as zf:
for member in zf.infolist():
member_path = os.path.normpath(member.filename)
destination = os.path.commonpath([base_dir, member_path])
if not destination.startswith(base_dir):
return jsonify({'error': 'Invalid path in archive'}), 400
zf.extract(member, base_dir)
return jsonify({'status': 'ok'}), 200
API key handling after extraction
After extraction, avoid automatically loading or exposing extracted key files through routes. If your application consumes API keys from files, ensure those files are not user-writable and are located outside publicly accessible paths.
import os
from flask import Flask
app = Flask(__name__)
# Load API keys from a secure, non-user-controlled location
KEY_DIR = os.path.join(os.path.dirname(__file__), 'secrets')
def get_api_key():
key_path = os.path.join(KEY_DIR, 'api_key.txt')
if not os.path.isfile(key_path):
return None
with open(key_path, 'r') as f:
return f.read().strip()
@app.route('/service-token')
def service_token():
key = get_api_key()
if key is None:
return jsonify({'error': 'Configuration unavailable'}), 500
return jsonify({'token': key})
Additional hardening
- Disable extraction of symbolic links in archives to prevent link-based escapes.
- Use a library or wrapper that supports safe extraction, or implement strict allow-lists for file extensions and directory depth.
- Store API keys in environment variables or managed secret stores rather than files extracted from user input.
These steps reduce the attack surface around Zip Slip and protect API key material. When combined with continuous scanning using tools such as middleBrick’s CLI (middlebrick scan <url>) or GitHub Action integration, you can detect path traversal issues before they reach production.