v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: MEDIUM auth.py.cors.allow-all

Flask-CORS allows any origin while credentials are enabled.

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

This configuration pairs supports_credentials=True with a wildcard origin (origins="*", origins=["*"], or no origins argument at all, since Flask-CORS defaults to *). The CORS spec forbids the Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true combination, so browsers will block it; the dangerous "fix" is to leave the wildcard in place while keeping credentials on, which exposes credentialed cross-origin access to ANY website (CWE-942). For OAuth/OIDC this leaks cookies, session tokens and CSRF protections cross-origin.

Credentialed requests must use an explicit allow-list of trusted origins, e.g. CORS(app, origins=["https://app.example.com"], supports_credentials=True). If you genuinely need a public, wildcard endpoint, drop credentials: CORS(app, origins="*") (the default, supports_credentials=False).

VULNERABLE
vulnerable.py
from flask import Flask
from flask_cors import CORS, cross_origin

app = Flask(__name__)


# ruleid: auth.py.cors.allow-all
CORS(app, origins="*", supports_credentials=True)


# ruleid: auth.py.cors.allow-all
CORS(app, supports_credentials=True, origins="*")


# ruleid: auth.py.cors.allow-all
CORS(app, origins=["*"], supports_credentials=True)


# Credentials on, no `origins` argument → Flask-CORS defaults to the wildcard.
# ruleid: auth.py.cors.allow-all
CORS(app, supports_credentials=True)


@app.route("/wildcard")
# ruleid: auth.py.cors.allow-all
@cross_origin(origins="*", supports_credentials=True)
def wildcard_view():
    return "data"


@app.route("/default")
# ruleid: auth.py.cors.allow-all
@cross_origin(supports_credentials=True)
def default_view():
    return "data"
SAFE
safe.py
from flask import Flask
from flask_cors import CORS, cross_origin

app = Flask(__name__)


# ok: auth.py.cors.allow-all -- credentials with an explicit allow-list
CORS(app, origins=["https://app.example.com"], supports_credentials=True)


# ok: auth.py.cors.allow-all -- explicit single origin with credentials
CORS(app, origins="https://app.example.com", supports_credentials=True)


# ok: auth.py.cors.allow-all -- wildcard origin but no credentials (public API)
CORS(app, origins="*")


# ok: auth.py.cors.allow-all -- default config, no credentials enabled
CORS(app)


@app.route("/authed")
# ok: auth.py.cors.allow-all -- explicit allow-list on the decorator
@cross_origin(origins=["https://app.example.com"], supports_credentials=True)
def authed_view():
    return "data"

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

# oauthlint-disable-next-line auth.py.cors.allow-all -- <reason>

References

https://flask-cors.readthedocs.io/en/latest/configuration.html ↗https://cwe.mitre.org/data/definitions/942.html ↗