Flask CORS Wildcard Origin

MEDIUM

Detects Flask-CORS configured with origins="*", allowing any domain to make cross-origin requests to the application.

Rule Information

Language
Python
Category
Flask
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythonflaskcorswildcardcross-originconfigurationmisconfigurationflask-corsCWE-942OWASP-A05
CWE References

Interactive Playground

Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.

pathfinder scan --ruleset python/PYTHON-FLASK-AUDIT-004 --project .
1
2
3
4
5
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

About This Rule

Understanding the vulnerability and how it is detected

This rule detects Flask applications that initialize Flask-CORS with a wildcard origin (origins="*"). The Access-Control-Allow-Origin: * header instructs browsers to allow any web page -- on any domain, including attacker-controlled sites -- to make cross-origin requests to the application and read the responses.

The critical risk arises when wildcard CORS is combined with credentials (cookies, HTTP auth, or client-side certificates). While browsers prevent credentials from being sent with a pure wildcard response, the misconfiguration often evolves: developers add supports_credentials=True and then change origins="*" to origins="null" or reflect the Origin header, inadvertently creating a credentialed CORS bypass. Auditing wildcard CORS early prevents this class of vulnerability from appearing in the first place.

The detection uses FlaskCORS.method("CORS").where("origins", "*") -- a QueryType-based precise match. FlaskCORS declares fqns=["flask_cors"], so only objects imported from the flask_cors package are matched. The .where("origins", "*") filter means only calls where the origins keyword argument is exactly the string "*" are flagged. Calls with a specific domain list, a regex, or a variable are not flagged. This precision delivers zero false positives on correctly configured applications.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

Cross-Origin Data Theft from Authenticated Users

With wildcard CORS, any malicious web page can make JavaScript fetch() calls to the application's API and read the JSON responses. If the user visiting the malicious page is already authenticated (via cookie or session), the request carries their credentials and the attacker's page can silently exfiltrate account data, private API responses, or internal state.

2

Cross-Site Request Forgery Amplification

Wildcard CORS allows attackers to use JavaScript XMLHttpRequest with full access to response bodies, not just fire-and-forget form submissions. This upgrades CSRF from blind state-changing attacks to data-reading attacks where the attacker can actually see what the server returns.

3

Credential-Based Bypass When supports_credentials Is Added Later

Applications often start with origins="*" and later add supports_credentials=True as authentication is added. At that point, browsers block the combination. Developers then change to reflecting the Origin header or using origins="null", both of which are exploitable. Fixing the wildcard origin early prevents this progression.

4

Internal API Exposure

Wildcard CORS on internal APIs (admin panels, management endpoints, metrics) allows any external website visited by a privileged user to make requests to those endpoints. Even if authentication is required, the attacker's page executes in the authenticated user's browser context.

How to Fix

Recommended remediation steps

  • 1Replace origins="*" with an explicit list of trusted origins -- for example, ["https://app.example.com", "https://admin.example.com"].
  • 2If you need to allow multiple environments (dev, staging, prod), maintain an allow-list per environment and inject it via configuration rather than hardcoding "*".
  • 3Never combine origins="*" with supports_credentials=True -- browsers block this and developers tend to work around it in insecure ways.
  • 4Restrict CORS to the minimum required HTTP methods (methods=["GET", "POST"]) rather than allowing all methods.
  • 5Audit CORS configuration changes in code review as a security-sensitive change, similar to changes to authentication middleware.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

This rule uses a QueryType-based precise match: FlaskCORS.method("CORS").where("origins", "*"). FlaskCORS declares fqns=["flask_cors"], restricting matches to objects imported from the flask_cors package. The .method("CORS") step targets the CORS() constructor call. The .where("origins", "*") step filters to calls where the origins keyword argument is exactly the string "*". Calls with a list of specific origins, a compiled regex, or a variable are not flagged. The rule operates at the call-site level without cross-file dataflow analysis.

Compliance & Standards

Industry frameworks and regulations that require detection of this vulnerability

OWASP Top 10
A05:2021 - Security Misconfiguration: restrict cross-origin access to trusted domains
CWE Top 25
CWE-942 Permissive Cross-domain Policy with Untrusted Domains
PCI DSS v4.0
Requirement 6.2.4 -- prevent cross-site attacks including insecure CORS policies
NIST SP 800-53
SC-8: Transmission Confidentiality and Integrity -- protect data from unauthorized cross-origin access

References

External resources and documentation

Similar Rules

Explore related security rules for Python

Frequently Asked Questions

Common questions about Flask CORS Wildcard Origin

Wildcard CORS (origins="*") is safe only for fully public, unauthenticated APIs that return no sensitive data -- for example, a public CDN or a read-only open data API with no authentication. For any API that uses cookies, sessions, API keys, or returns user-specific data, wildcard CORS is a vulnerability.
Without .where(), the rule would flag every CORS() call regardless of the origins value, producing false positives on applications with proper origin allow-lists. The .where("origins", "*") constraint means only the literal string "*" triggers a finding. CORS(app, origins=["https://example.com"]) is not flagged.
Browsers do block Access-Control-Allow-Credentials: true with Access-Control-Allow-Origin: *. However, many APIs do not use cookies and instead use tokens in headers -- those requests work fine with wildcard CORS. Additionally, developers who hit the credential-blocking error often switch to reflecting the Origin header (effectively any-origin) as a workaround, which is exploitable. Flagging wildcard early prevents the whole pattern.
Maintain a per-environment allow-list and inject it through configuration: allowed_origins = os.getenv("CORS_ORIGINS", "https://app.example.com").split(",") CORS(app, origins=allowed_origins) This way, no environment has wildcard origins hardcoded in source code.
Run: pathfinder ci --ruleset python/flask/PYTHON-FLASK-AUDIT-004 --project . The rule outputs SARIF, JSON, or CSV and can post inline pull request comments on GitHub.
No. This rule matches the CORS() constructor call pattern. Per-route decorators such as @cross_origin(origins="*") are a separate pattern not covered here. A dedicated rule for the @cross_origin decorator would complement this one.
Use Flask-CORS's resource-specific configuration to restrict wildcard CORS to specific URL patterns: CORS(app, resources={r"/public/*": {"origins": "*"}}). This limits the wildcard to routes that genuinely require it rather than applying it globally.

New feature

Get these findings posted directly on your GitHub pull requests

The Flask CORS Wildcard Origin rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.

See how it works