TL;DR
The Access-Control-Allow-Headers header controls which request headers are allowed during cross-origin requests. If it’s too permissive (e.g., using *) or missing expected headers, attackers can potentially bypass CORS security. This guide shows how this happens and how to fix it.
Understanding the Problem
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that restricts web pages from making requests to a different domain than the one which served the web page. The Access-Control-Allow-Headers header tells the browser which custom headers are permitted in cross-origin requests.
If a server incorrectly configures this header, it can open up vulnerabilities. Common issues include:
- Using
*: Allowing all headers is generally unsafe. - Missing Expected Headers: If the browser sends a header that isn’t listed in
Access-Control-Allow-Headers, the request will be blocked (preflight failure).
How an Attack Works
An attacker can craft a malicious web page that attempts to send custom headers not allowed by the server. If the server doesn’t properly validate these headers, it could lead to unintended consequences like:
- Information Disclosure: The attacker might be able to read sensitive data they shouldn’t have access to.
- Cross-Site Request Forgery (CSRF): Bypassing CORS can make CSRF attacks easier.
Solution Steps
- Identify the Vulnerable Endpoint: Determine which API endpoint is affected by the incorrect
Access-Control-Allow-Headersconfiguration. Use your browser’s developer tools (Network tab) to inspect the CORS headers during a cross-origin request. - Check Current Header Configuration: Examine the server’s response headers for the
Access-Control-Allow-Headersheader. For example, usingcurl -I https://example.com/api/data, you can view the headers returned by the API endpoint.
- Restrict Allowed Headers: Modify your server’s configuration to explicitly list only the necessary custom headers in
Access-Control-Allow-Headers. Avoid using*.- Example (Apache): Add or modify the following in your
.htaccessfile:Header set Access-Control-Allow-Headers "Content-Type,Authorization" - Example (Node.js/Express):
app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); });
- Example (Apache): Add or modify the following in your
- Validate Headers on the Server: Even with a restricted
Access-Control-Allow-Headerslist, always validate the actual headers received by your server. This adds an extra layer of security.- Ensure that any custom header values are what you expect.
- Sanitize and escape header data to prevent injection attacks.
- Test the Fix: After making changes, thoroughly test the endpoint with cross-origin requests.
- Attempt to send a request with an unauthorized header. The request should be blocked by the browser.
- Verify that legitimate requests with allowed headers are still functioning correctly.
Important Considerations
- Preflight Requests: Remember that browsers send a preflight
OPTIONSrequest before the actual cross-origin request to check CORS compatibility. Ensure your server handles these requests correctly and returns appropriate headers. - Wildcard Usage: While sometimes unavoidable, using wildcards (e.g.,
*) in CORS headers should be done with extreme caution and only when absolutely necessary.

