What OWASP guidance says about CORS misconfiguration

OWASP's Web Security Testing Guide treats a permissive cross-origin policy as "very insecure and is not acceptable in general terms, except in the case of a public API."[1] In practice, a CORS misconfiguration means your server tells browsers that untrusted sites may read its responses. MITRE files this under CWE-942.[2] How serious it is depends on whether credentials are allowed and what data the response carries.
What OWASP's testing guide says CORS misconfiguration is
OWASP's Web Security Testing Guide (WSTG) defines the problem by its effect: a policy that lets any origin make cross-origin requests is "very insecure" unless the endpoint is a genuinely public API.[1] So `Access-Control-Allow-Origin: *` on a public, read-only data feed can be fine, while the same header on an account API is a finding.
The guide also warns against trusting the `Origin` header as an access control mechanism. Browsers set it, but anyone sending requests outside a browser can write whatever value they like, so OWASP says relying on this header for access control checks "is not a good idea."[1] The header tells the server where a browser request claims to come from. It does not prove who is asking.
The pattern WSTG tells testers to look for first is the wildcard: a tester "can check if the Access-Control-Allow-Origin: * exists in the HTTP response messages."[1] The more dangerous variants usually come from servers that try to be selective and get the matching logic wrong.
Which CWE and OWASP category CORS falls under
The standard MITRE classification for CORS misconfiguration is CWE-942: Permissive Cross-domain Policy with Untrusted Domains. MITRE describes a product that uses a web-client protection mechanism such as a cross-domain policy, where "the policy includes untrusted domains with which the web client is allowed to communicate."[2] A CORS allowlist that trusts the wrong origins fits that definition exactly.
Individual CVE advisories sometimes record a different, narrower weakness when the root cause is broken origin validation rather than an overly broad policy. When you write up or triage a specific finding, use the CWE listed in that advisory instead of assuming CWE-942. For example, CVE-2024-8183 covers "a CORS (Cross-Origin Resource Sharing) misconfiguration in prefecthq/prefect prior to version 3.0.3"[3], and its advisory carries its own CWE and score.
The OWASP Top 10 mapping is less settled. Scanners and blogs assign CORS findings to different Top 10 categories, so treat any one mapping as that tool's choice, not an OWASP ruling. The OWASP document that addresses CORS directly is the WSTG chapter on testing cross-origin resource sharing.[1]
How to check your own site for CORS misconfiguration
The manual check takes a few minutes with an intercepting proxy or `curl`. Send requests to your authenticated endpoints with a crafted `Origin` header and read two response headers: `Access-Control-Allow-Origin` and `Access-Control-Allow-Credentials`. Start with the wildcard check OWASP describes, then move on to origin reflection.[1]
Try these origins against each endpoint that returns user data:
- A domain you control, such as `https://attacker.example`. If the server echoes it back, it is reflecting any origin.
- Your own domain with extra text appended, such as `https://yoursite.com.attacker.example`. This catches prefix matching.
- A domain that ends with your name, such as `https://notyoursite.com`. This catches suffix matching.
- `null`, which some servers accept by mistake.
The prefix and suffix tests come from real bug bounty findings. In one case a site "trusted all Origins that started with https://btc.net, including https://btc.net.evil.net", and in another a server "trusts all origins that ended in advisor.com, including definitelynotadvisor.com."[4] If any test returns your crafted origin together with `Access-Control-Allow-Credentials: true`, you have a finding worth fixing first.
For request-by-request examples and what each response means, see the full walkthrough on checking for CORS misconfiguration on your own site.
What a CORS misconfiguration lets an attacker do
A CORS misconfiguration lets a malicious website use the victim's own browser to read data from your application. Tenable describes it as making "the client browser act as a proxy between a malicious website and the target web application."[5] The victim only has to visit the attacker's page while logged in to your site.
The attack runs in four steps. The attacker's page sends a request to your API from the victim's browser. The browser attaches the victim's cookies. Your server answers with a CORS header that trusts the attacker's origin. The browser then hands the response to the attacker's script. OWASP sums up the result: "the attacker can read the response afterwards and access sensitive information that is only accessible by a victim user."[1]
PortSwigger's research into bug bounty targets showed how real this is, including the prefix and suffix matching flaws above. The fix can also be fast: one reported issue "was patched within an astounding 20 minutes."[4] For more attack scenarios, read what a CORS misconfiguration vulnerability actually allows attackers to do.
Why no single CVSS score fits CORS misconfiguration
No standard CVSS score exists for "CORS misconfiguration" because the same weakness can expose nothing or expose everything. A wildcard on a public API may be acceptable by OWASP's own standard[1], while the Prefect flaw "allows unauthorized domains to access sensitive data."[3] Those two cases should not get the same score.
Three factors move the score most:
- Credentials. Tenable notes that "the risk increases when the CORS policy allows the usage of requests with credentials."[5] Without credentials, an attacker usually reads only what is already public.
- Data in the response. Session tokens, API keys and personal data raise the confidentiality impact. A response holding only public content lowers it.
- Who can be targeted. If the endpoint only serves logged-in users, the attack needs a logged-in victim to visit the attacker's page, which affects the user interaction and privilege metrics.
Score each finding from its own vector, and check the published advisory when one exists. For a step-by-step scoring example, see how a CORS misconfiguration CVSS score gets decided.
| Misconfiguration pattern | Real-world example | What drives severity | Source |
|---|---|---|---|
| Wildcard Access-Control-Allow-Origin | Acceptable only for a public API, per OWASP | Whether the endpoint returns non-public data | OWASP WSTG |
| Prefix-matched origin | btc.net trusted btc.net.evil.net | Credentials allowed plus sensitive responses | PortSwigger |
| Suffix-matched origin | advisor.com trusted definitelynotadvisor.com | Credentials allowed plus sensitive responses | PortSwigger |
| Unauthorized domains allowed | CVE-2024-8183, Prefect before 3.0.3 | Sensitive data readable by other domains | GitLab Advisory Database |
How to fix a CORS misconfiguration
The fix is to trust only the exact origins you name, and to send credentials to as few of them as possible. That removes the defect MITRE describes, a policy that includes untrusted domains.[2] The Prefect project resolved its CORS issue in version 3.0.3[3], so for third-party software, upgrading is the first step.
For your own code:
- Use an explicit allowlist. Compare the incoming `Origin` against a fixed list of full origins (scheme, host and port). Never echo the request's `Origin` back unchecked.
- Keep wildcards for public data only. OWASP accepts a permissive policy only for a public API.[1]
- Limit credentials. Send `Access-Control-Allow-Credentials: true` only for origins you fully control.
- Anchor every pattern. If you must use a regex, anchor both ends and escape the dots, so that `btc.net.evil.net` and `definitelynotadvisor.com` style bypasses fail.[4]
- Reject `null`. Do not put the `null` origin on your allowlist.
- Remove CORS headers where they are not needed. Endpoints that never serve cross-origin requests should send no CORS headers at all.
- Keep real access control on the server. The `Origin` check is a browser-side safeguard, not authentication.[1]
For framework-specific settings, see mitigation fixes for each common CORS mistake.
Why AI-built sites keep shipping permissive CORS
Sites generated with AI coding tools often ship whatever CORS setting made the frontend work first, and nobody reviews it before launch. BattleTester started from that problem.
A free surface scan is a quick first step and needs no credit card. If your app handles logins or sensitive data, a full pentest goes deeper and costs $15, charged only if the scan finds High or Critical vulnerabilities. Every report rates findings by severity and includes reproduction steps for each issue. BattleTester is not a comprehensive security audit, so for high-stakes systems, also bring in qualified security professionals.
FAQ
Is CORS misconfiguration actually in the OWASP Top 10?
Not as its own named item. Different scanners file it under different Top 10 categories, so in a report, cite the CWE and the OWASP testing guide chapter instead of a Top 10 category number.
How severe is a CORS misconfiguration, really?
It ranges from informational to serious. A wildcard on public data is usually low risk. A reflected origin with credentials on an endpoint that returns account data is the version worth fixing the same day.
What does a real CORS misconfiguration bug bounty report look like?
A strong report shows the exact request with the crafted Origin header, the response headers proving the origin was trusted with credentials, and a small proof-of-concept page that reads a logged-in user's data. Programs often reject reports that only show a wildcard header with no sensitive data behind it.
Are there real CVEs caused by CORS misconfiguration?
Yes. CVE-2024-8183 in the Prefect workflow tool is one, fixed in version 3.0.3. To find others, search CVE databases for CWE-942 and read each advisory's own score, because they differ.
Sources
- WSTG - Testing Cross Origin Resource Sharing, OWASP, accessed October 22, 2026
- CWE-942: Permissive Cross-domain Policy with Untrusted Domains, MITRE, accessed October 22, 2026
- CVE-2024-8183 - Prefect CORS misconfiguration advisory, GitLab Advisory Database, accessed October 22, 2026
- Exploiting CORS misconfigurations for Bitcoins and bounties, PortSwigger, accessed October 22, 2026
- Understanding Cross-Origin Resource Sharing Vulnerabilities, Tenable, accessed October 22, 2026