Decloak is an AI-powered web security intelligence platform that scans a site's HTTP/TLS posture, JavaScript, and third-party scripts to produce a report anyone can read. This guide is part of Decloak's library of practical, source-backed security guidance.
In this guide
- Key takeaways
- What does the Access-Control-Allow-Origin header do?
- Can I list multiple origins in a single Access-Control-Allow-Origin header?
- When is it safe to use the wildcard `*`?
- How should I handle requests that include credentials?
- Why is the `null` value discouraged?
- How do I prevent cache leakage when using dynamic origins?
- Example server - side implementation (Node.js/Express)
- How does this relate to web security scanning?
- What should you do if a scan reports an open CORS issue?
- When might you deliberately use `*`?
- Summary
Key takeaways
- Use either
*or a single exact origin value, never a comma - separated list. - Do not combine
*withAccess-Control-Allow-Credentials: true; instead echo a validated origin. - Add
Vary: Originwhenever the header value changes per request to prevent cache leakage. - Validate the incoming
Originagainst a whitelist before echoing it back.
What does the Access-Control-Allow-Origin header do?
The header tells the browser whether the response may be shared with a script running on a given origin. It is the core part of the CORS response flow and works together with other CORS headers such as Access-Control-Allow-Credentials.
Can I list multiple origins in a single Access-Control-Allow-Origin header?
No. The specification allows only one value: either the wildcard * or a single origin string. If you need to support several origins you must set the header dynamically for each request.
When is it safe to use the wildcard *?
The wildcard is safe only for requests that do not include credentials (cookies, HTTP auth, client - side certificates). If the request contains credentials, the browser will reject a response that uses *.
How should I handle requests that include credentials?
When Access-Control-Allow-Credentials: true is present, you must send an explicit origin that matches the request's Origin header. Echo the origin only after verifying it against an allow - list on the server; otherwise you expose an open - redirect style CORS vulnerability.
Why is the null value discouraged?
null represents a null origin such as file: or data: URLs. Any document can produce a null origin, so allowing it effectively opens your resource to any source. Use an explicit origin whitelist instead.
How do I prevent cache leakage when using dynamic origins?
When you return a specific origin (not *), include the response header Vary: Origin. This directs shared caches to store separate copies per origin, preventing one user's data from being served to another origin.
Example server - side implementation (Node.js/Express)
const allowedOrigins = [
"https://app.example.com",
"https://admin.example.com"
];
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Vary", "Origin");
res.setHeader("Access-Control-Allow-Credentials", "true");
} else {
// No CORS headers for disallowed origins
}
next();
});
This code validates the incoming Origin against a whitelist, echoes the origin, and adds Vary: Origin.
How does this relate to web security scanning?
A scanner like Decloak checks the Access-Control-Allow-Origin header as part of its core static HTML analysis and rendered - page network behaviour layers. It flags use of * together with credentials and missing Vary: Origin as misconfigurations, helping you catch open - CORS bugs before they are exploited.
What should you do if a scan reports an open CORS issue?
- Review the reported endpoint and confirm whether credentials are allowed.
- Replace
*with an explicit origin or a whitelist - based echo. - Add
Vary: Originto the response. - Re - run the scan to verify the fix.
When might you deliberately use *?
If the resource is truly public and never accessed with credentials - such as a public CDN asset - you can safely use *. Document the decision and ensure no authentication data is ever sent with those requests.
Summary
The Access-Control-Allow-Origin header is simple but powerful. Use a single explicit origin for credentialed requests, avoid the null value, and always add Vary: Origin when the header varies per request. Scanners will highlight these settings, giving you a quick way to verify compliance.
Related guides
How to Fix a Missing Content - Security - Policy Header
Learn concrete steps to add, test, and harden a Content - Security - Policy header, from server configuration to iterative reporting and verification.
Is HTTP 1.1 a security risk?
HTTP 1.1 is not a direct vulnerability, but its plain - text design and parsing ambiguities can create attack surfaces that need mitigation, especially when not used over TLS.
Is JavaScript a security risk?
JavaScript can be a major attack surface because injected scripts run with the same privileges as the page, but proper sanitization, CSP, and safe frameworks eliminate most risks.