How a CORS misconfiguration CVSS score is decided

A CORS misconfiguration has no single CVSS score. The score comes from the CVSS 3.1 base metrics applied to the specific flaw: which origins the server trusts, whether it allows credentials, and what data a foreign origin can read as a result. The same header mistake can rate Medium on one endpoint and High on another, and the biggest swing factor is credentials.
What a CORS misconfiguration actually is
A CORS misconfiguration is a cross-origin policy that trusts more origins than it should. CORS lets a server tell the browser which other origins may read its responses. When that list is too wide, a page on an untrusted site can read responses it was never meant to see.
The most common version is a server that copies the request's Origin header straight into Access-Control-Allow-Origin. PortSwigger describes reflecting origins without validation as readily exploitable, because it means any domain can access resources from the vulnerable one[1].
The attack runs in a victim's browser. The victim loads a page the attacker controls, that page sends a request to your app, and the browser hands the response to the attacker's script if your CORS headers allow it.
How CVSS 3.1 scores a CORS finding
CVSS 3.1 does not score the word CORS. It scores a specific flaw through its base metrics: Attack Vector, Attack Complexity, Privileges Required, User Interaction, Scope, and the three impact metrics for Confidentiality, Integrity and Availability. The definitions in the FIRST specification decide each value, and the values decide the score[2].
For a CORS finding, three of those metrics do most of the moving. The definitions in the table below are taken from the FIRST specification[2]. The right-hand column is how each one applies to a cross-origin read.
| CVSS 3.1 metric | What the definition says | Effect on a CORS finding |
|---|---|---|
| Scope: Unchanged | The exploited vulnerability can only affect resources managed by the same security authority. | Applies when the attacker reads data from the vulnerable app itself and nothing beyond it. |
| Confidentiality: High | Total loss of confidentiality, with all resources in the impacted component divulged to the attacker. | Fits when a foreign origin can read everything the logged-in victim can. A narrower read argues for a lower value. |
| Attack Complexity: High | A successful attack depends on conditions beyond the attacker's control. | Fits when only certain origins are trusted and the attacker must first get control of one. It does not fit when any origin is reflected. |
Work through the metrics for the endpoint in front of you, not for the category. Two findings with the same header pattern will get different vectors if one endpoint returns account data and the other returns a public product list.
Why the same CORS mistake gets different scores
The score varies mainly because of credentials. If the server allows credentialed cross-origin requests from an untrusted origin, the attacker's page reads the response as the logged-in victim. If it does not, the attacker gets only what the server returns to an anonymous visitor.
This is why a wildcard on its own is weaker than it looks. When a request carries credentials and the response uses the Access-Control-Allow-Origin wildcard, the browser blocks access to the response and reports a CORS error[3]. For credentialed requests the server must name an explicit origin instead of the wildcard[3]. A server that reflects the Origin header and also allows credentials has no such protection, which is what makes that combination the serious one.
Which origins are trusted matters too. A Sentry security advisory describes an API that incorrectly returned access-control-allow-credentials: true whenever the Origin request header ended with the installation's configured base hostname[4]. That flaw was credentialed, but only for origins matching that rule, so an attacker needed a matching origin before anything could be read. Conditions like that feed the Attack Complexity metric.
The last variable is the data. Confidentiality impact follows what is actually exposed: the High value is defined as a total loss of confidentiality in the impacted component[2]. An endpoint that returns a session token or personal records supports a higher value than one that returns a feature flag.
Where CORS fits in CWE and scanner taxonomies
Most CORS misconfigurations are filed under CWE-942, Permissive Cross-domain Security Policy with Untrusted Domains. MITRE defines it as a product that uses a web-client protection mechanism such as a Content Security Policy or cross-domain policy file, where the policy includes untrusted domains the web client is allowed to communicate with[5].
Scanners use their own issue names on top of that. PortSwigger, for example, has a separate issue for a CORS policy that trusts all subdomains and classes it under CWE-942[6]. Each scanner also attaches its own severity label to its own issue types.
Neither a CWE nor a scanner label is a CVSS score. A CWE names the kind of weakness. The score for a specific published issue comes from the vendor's advisory or its NVD entry, and the score for a finding on your own app comes from the vector you or your tester work out for it.
When a CORS finding becomes a paid pentest
Severity also decides billing on BattleTester, so the rating of a CORS finding has a direct practical effect. A CORS finding rated Medium does not trigger a charge on its own. One rated High or Critical is the kind that does.
If a full pentest finds no High or Critical vulnerabilities, you are not charged and the report stays fully accessible. So a run whose worst result is a Medium CORS finding still leaves you with the complete report.
BattleTester is not a comprehensive security audit and does not replace an assessment by qualified security professionals. If a credentialed CORS flaw exposes regulated or customer data, bring in a professional tester to confirm the impact.
What a CORS report should include
A CORS report should let the reader reproduce the finding and check the severity without trusting the author. For each affected endpoint, include:
- The exact Origin header sent in the request.
- The response headers returned, in full, including Access-Control-Allow-Origin and Access-Control-Allow-Credentials.
- Whether credentials were allowed, and what the response contained when they were.
- The CVSS 3.1 vector string next to the score, so each metric choice can be challenged.
Rate the severity from the vector, not from the issue name. If you claim High Confidentiality impact, show the data that supports it, since the definition is a total loss of confidentiality in the impacted component[2]. A report that only shows a reflected origin on an endpoint with no sensitive data should say so and carry a lower rating.
Our reports include reproduction steps for every issue, with findings rated by severity.
Fixing it and checking your own site
Fix a CORS misconfiguration by replacing wildcard and reflected origins with an explicit allowlist of the origins you actually trust. Do not echo the request's Origin header back without validating it, since unvalidated reflection is readily exploitable[1]. Where an endpoint needs credentials, return one explicit origin, because the wildcard is not permitted for credentialed requests[3].
The right change depends on which mistake you have. Our guide to CORS misconfiguration mitigation fixes for each common mistake covers them one by one. To confirm the fix, or to find out whether you have the problem at all, follow the steps in how to check for CORS misconfiguration on your own site.
For a wider look at your app, you can start a free surface scan with no credit card required upfront.
FAQ
Is a CORS misconfiguration high or medium severity?
It can be either. The rating depends on the vector for the specific endpoint: a flaw that lets any origin read a logged-in user's data rates higher than one that exposes only public responses or trusts a narrow set of origins.
Is a wildcard Access-Control-Allow-Origin always a vulnerability?
No. It is a normal setting for responses meant to be public, and the browser blocks a credentialed response that uses the wildcard[3]. It becomes a finding when the response an anonymous request gets back contains something that should not be public.
How do I check my own site for a CORS misconfiguration?
Send requests with different Origin headers to your endpoints and compare the Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers that come back. If you use BattleTester, you must verify ownership of the site first, with a meta tag in the HTML head or a verification file in the site root.
Sources
- Cross-origin resource sharing (CORS), PortSwigger Web Security Academy, accessed October 4, 2026
- Common Vulnerability Scoring System version 3.1 Specification Document, FIRST, accessed October 4, 2026
- Cross-Origin Resource Sharing (CORS), MDN Web Docs, accessed October 4, 2026
- [Security Advisory]: CORS misconfiguration, Sentry (getsentry/security-advisories), accessed October 4, 2026
- CWE-942: Permissive Cross-domain Security Policy with Untrusted Domains, MITRE CWE, accessed October 4, 2026
- Cross-origin resource sharing: all subdomains trusted, PortSwigger, accessed October 4, 2026