HIGH missing tlsflaskapi keys

Missing Tls in Flask with Api Keys

Missing Tls in Flask with Api Keys — how this specific combination creates or exposes the vulnerability

Serving API keys over unencrypted HTTP in a Flask application exposes both the transport and the secret itself. Without TLS, an attacker on the same network can observe or modify traffic between the client and the server. Because API keys are typically static bearer tokens, interception grants immediate unauthorized access to the associated API or service.

Consider a Flask route that returns a stored API key or expects it in a request header:

from flask import Flask, request, jsonify

app = Flask(__name__)

# Example: storing keys in memory for illustration only
API_KEYS = {
    "service_a": "ak_live_abc123",
    "service_b": "ak_live_xyz789",
}

@app.route("/v1/resource")
def get_resource():
    key = request.headers.get("X-API-Key")
    if not key or key not in API_KEYS.values():
        return jsonify({"error": "unauthorized"}), 401
    return jsonify({"data": "sensitive"}), 200

If this endpoint is reachable over HTTP, any party on the network path can capture the key from request headers or responses. The risk is compounded when the same key is used across multiple services or environments, as a single interception may lead to lateral movement. In a typical man-in-the-middle scenario, the attacker passively collects keys and can then reuse them until rotation occurs.

middleBrick’s unauthenticated scans include checks for encryption (TLS) and inspect how API keys are handled during transmission. When TLS is missing, findings in the Data Exposure and Authentication categories highlight the exposure of static credentials in transit. Because API keys function as long-lived bearer tokens, the absence of encryption effectively undermines their intended confidentiality.

Additionally, without TLS, there is no integrity guarantee. An attacker can modify requests or responses, potentially injecting malicious payloads or altering authorization decisions. This intersects with Authentication and Input Validation checks, as the server may accept tampered headers without detecting manipulation. The combination of static API keys and missing transport protection therefore creates a high-impact attack surface where credential theft and request forgery become trivial.

Api Keys-Specific Remediation in Flask — concrete code fixes

Remediation focuses on enforcing transport confidentiality and reducing the exposure and impact of API keys. The primary step is to serve all endpoints over HTTPS with a valid certificate, ensuring encryption in transit. Below are concrete Flask patterns that integrate API keys safely under TLS.

1. Enforce HTTPS in Flask

Use a production WSGI server (e.g., Gunicorn) terminated by a TLS-terminating proxy or load balancer. In development, you can enforce redirect to HTTPS:

from flask import Flask, request, jsonify, redirect

app = Flask(__name__)

@app.before_request
def enforce_https():
    if not request.is_secure:
        url = request.url.replace("http://", "https://", 1)
        return redirect(url, code=301)

API_KEYS = {
    "service_a": "ak_live_abc123",
}

@app.route("/v1/resource")
def get_resource():
    key = request.headers.get("X-API-Key")
    if not key or key not in API_KEYS.values():
        return jsonify({"error": "unauthorized"}), 401
    return jsonify({"data": "sensitive"}), 200

Note: In production, rely on your infrastructure’s TLS termination rather than Flask’s built-in server. The above is for development guidance only.

2. Store and compare keys securely

Avoid storing raw keys in code or global variables. Use environment variables and constant-time comparison to prevent timing attacks:

import os
import hmac
from flask import Flask, request, jsonify

app = Flask(__name__)

# Load expected key from environment (set outside source code)
EXPECTED_KEY = os.environ.get("API_KEY")

@app.route("/v1/resource")
def get_resource():
    provided = request.headers.get("X-API-Key")
    if not provided or not EXPECTED_KEY or not hmac.compare_digest(provided, EXPECTED_KEY):
        return jsonify({"error": "unauthorized"}), 401
    return jsonify({"data": "sensitive"}), 200

3. Rotate keys and avoid long-lived static keys

While code can mitigate transport risks, static keys remain high value. Integrate key rotation and scope limitation (per-service, per-client). For short-lived access, consider issuing tokens via an authorization server rather than long-lived API keys.

4. Use middleware for key validation

Centralize validation to avoid repetitive checks and reduce human error:

from flask import Flask, request, jsonify

app = Flask(__name__)

def require_api_key(view_func):
    def wrapper(*args, **kwargs):
        if request.headers.get("X-API-Key") != "REPLACE_WITH_VALID_KEY":
            return jsonify({"error": "forbidden"}), 403
        return view_func(*args, **kwargs)
    return wrapper

@app.route("/v1/resource")
@require_api_key
def get_resource():
    return jsonify({"data": "protected"}), 200

These patterns, combined with mandatory TLS, reduce the likelihood of key interception and misuse. middleBrick’s scans can verify the presence of encryption and flag endpoints that transmit API keys in cleartext, enabling teams to remediate findings before exposure in production.

Related CWEs: encryption

CWE IDNameSeverity
CWE-319Cleartext Transmission of Sensitive Information HIGH
CWE-295Improper Certificate Validation HIGH
CWE-326Inadequate Encryption Strength HIGH
CWE-327Use of a Broken or Risky Cryptographic Algorithm HIGH
CWE-328Use of Weak Hash HIGH
CWE-330Use of Insufficiently Random Values HIGH
CWE-338Use of Cryptographically Weak PRNG MEDIUM
CWE-693Protection Mechanism Failure MEDIUM
CWE-757Selection of Less-Secure Algorithm During Negotiation HIGH
CWE-261Weak Encoding for Password HIGH

Frequently Asked Questions

Does using API keys over HTTP leak credentials even if the key is rotated frequently?
Yes. Any unencrypted transmission can be intercepted in real time. Frequent rotation reduces the window of exposure but does not eliminate the risk of capture during the period a key is valid.
Is an HTTPS-only Flask app enough to protect API keys?
HTTPS protects keys in transit, but additional controls are recommended: store keys in environment variables, use constant-time comparison, avoid hardcoded keys, and rotate keys periodically to limit impact if compromised.