HIGH cors wildcardflaskbasic auth

Cors Wildcard in Flask with Basic Auth

Cors Wildcard in Flask with Basic Auth — how this specific combination creates or exposes the vulnerability

A Cross-Origin Resource Sharing (CORS) wildcard (Access-Control-Allow-Origin: *) combined with HTTP Basic Authentication in a Flask application creates a significant security misconfiguration. When a server responds with a wildcard CORS policy while also requiring Basic Auth, it may permit unauthorized cross-origin requests to carry valid authentication credentials.

In Flask, developers sometimes apply a CORS middleware or route-level headers that set Access-Control-Allow-Origin: *. If the same routes also accept and validate Basic Auth credentials (sent via the Authorization: Basic header), browsers will allow the cross-origin request to proceed and expose the authenticated response to the originating site. This violates the principle that wildcard origins should not be used when credentials are involved.

The browser’s CORS implementation treats the combination as dangerous: a webpage served from https://evil.com can make a XMLHttpRequest or fetch call to the authenticated endpoint, and if the server responds with *, the browser delivers the response to the attacker’s script. Even though the request includes an Authorization header, the server may still process it and return sensitive data, thinking the origin is unrestricted.

Consider an authenticated metrics endpoint /api/v1/metrics protected by Basic Auth. If the Flask app sets:

resp = make_response(jsonify(metrics))
resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers['Access-Control-Allow-Headers'] = 'Authorization'

and also validates the Basic Auth credentials, a malicious site can read the response. This is especially relevant when the Basic Auth credentials are static or shared across services, increasing the risk of accidental exposure.

Attack patterns enabled by this misconfiguration include cross-origin credential theft and unauthorized data access. While this is not a server-side code injection or a traditional OWASP API Top 10 Broken Object Level Authorization (BOLA), it is a dangerous information exposure that can be chained with other weaknesses. Tools like middleBrick can detect such risky header combinations during an unauthenticated scan, highlighting the need for tighter CORS and authentication alignment.

Basic Auth-Specific Remediation in Flask — concrete code fixes

Remediation centers on avoiding wildcard origins when credentials are in use and explicitly allowing only trusted origins. In Flask, you should set Access-Control-Allow-Origin to a specific origin or dynamically reflect a safe origin rather than using *. When Basic Auth is enabled, ensure CORS headers are applied conditionally.

Below are concrete, working Flask examples that implement secure CORS with Basic Auth. The first example uses a simple hardcoded origin; the second demonstrates a dynamic origin check to allow a list of trusted domains.

Example 1: Fixed allowed origin with Basic Auth

from flask import Flask, request, Response, jsonify
import base64

app = Flask(__name__)

VALID_USER = 'admin'
VALID_PASS = 's3cret'

@app.before_request
def authenticate():
    if request.path.startswith('/api/'):
        auth = request.authorization
        if not auth or not (auth.username == VALID_USER and auth.password == VALID_PASS):
            return Response('Could not verify your access level.', 401, {'WWW-Authenticate': 'Basic'})

@app.route('/api/metrics')
def metrics():
    data = {'cpu': 42, 'memory': 68}
    resp = jsonify(data)
    resp.headers['Access-Control-Allow-Origin'] = 'https://trusted.example.com'
    resp.headers['Access-Control-Allow-Headers'] = 'Authorization'
    resp.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
    return resp

Example 2: Dynamic origin validation for multiple trusted origins

from flask import Flask, request, Response, jsonify
import base64

app = Flask(__name__)

VALID_USER = 'admin'
VALID_PASS = 's3cret'
TRUSTED_ORIGINS = {'https://app.example.com', 'https://dashboard.example.com'}

def authenticate():
    if request.path.startswith('/api/'):
        auth = request.authorization
        if not auth or not (auth.username == VALID_USER and auth.password == VALID_PASS):
            return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic'})

@app.before_request
def check_auth(): 
    authenticate()

@app.route('/api/metrics')
def metrics():
    data = {'cpu': 42, 'memory': 68}
    resp = jsonify(data)
    origin = request.headers.get('Origin')
    if origin in TRUSTED_ORIGINS:
        resp.headers['Access-Control-Allow-Origin'] = origin
        resp.headers['Access-Control-Allow-Headers'] = 'Authorization'
        resp.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
    return resp

In both examples, the server validates Basic Auth credentials before returning a response. The CORS header is set to a specific origin from a trusted set, preventing wildcard exposure. For broader integration, teams using the middleBrick CLI can scan their endpoints with middlebrick scan <url> to verify that no wildcard origins appear alongside authentication headers.

Additional best practices include:

  • Never set Access-Control-Allow-Origin: * when endpoints require authentication headers.
  • Prefer token-based authentication (e.g., OAuth2 or API keys) over Basic Auth for cross-origin scenarios, or ensure credentials are scoped and short-lived.
  • Explicitly define Access-Control-Allow-Methods and Access-Control-Allow-Headers to reduce unnecessary exposure.
  • Use the middleBrick GitHub Action to enforce these rules in CI/CD, failing builds if risky CORS configurations are detected.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Why is using 'Access-Control-Allow-Origin: *' dangerous with Basic Auth?
Because it allows any origin to read authenticated responses, potentially exposing credentials and sensitive data to malicious websites via cross-origin requests.
How can I test my Flask endpoints for CORS and Basic Auth misconfigurations?
Use the middleBrick CLI to scan your API: run middlebrick scan <your-endpoint-url>. It will report CORS and authentication findings without requiring credentials.