# Reflected-origin CORS with credentials

Origin echoed into ACAO with credentials; validator parses origin differently than the browser

_Area: Web access control and IDOR. Seen in 3 disclosed reports; 2 confirmed bounties: $500 and $3,134; latest 2020-11-13. Updated 2026-10-23._

## How it works
A server copies the request's `Origin` into `Access-Control-Allow-Origin` and sets `Access-Control-Allow-Credentials: true`. The intended guard is an allowlist check, but the check parses the origin differently than the browser does. Where the validator splits on a separator the hostname grammar also accepts, an attacker-controlled origin can pass the check while the browser still treats it as a distinct origin. The browser then hands the authenticated response to the attacker page, defeating the same-origin policy. A simpler failure is a plain misconfig: no allowlist at all, just reflection.

## Where it shows up
- `Access-Control-Allow-Origin` set from the request header rather than a fixed value.
- `Access-Control-Allow-Credentials: true` on endpoints returning session data or PII.
- Origin validation using `contains`, `endsWith`, or a split on `.`/`:` without anchoring.
- Adjacent pattern: extension background scripts that fetch a URL supplied by a content script and return the body [E1](https://bugbountylibrary.com/r/blog%3Alf-lc-vrp-145304705.md).

## How to review
Invariant: the value written to `Access-Control-Allow-Origin` must be an exact, full-string match against a fixed allowlist, never derived from attacker-influenced input. Verify a foreign `Origin` is rejected, not echoed. Check characters valid in hostnames but not in the validator's split logic (backtick, percent) [E2](https://bugbountylibrary.com/r/blog%3Acorben-io-blog-17-11-27-tricky-cors.md). Confirm the comparison is anchored at both ends and uses the browser's parsing. For extensions, the background message handler must not accept attacker-controlled URL, method, or headers and perform credentialed requests for the renderer [E1](https://bugbountylibrary.com/r/blog%3Alf-lc-vrp-145304705.md).

## Variants seen
- Backtick (`%60`) accepted as a subdomain separator, letting an attacker domain be appended to a trusted origin [E2](https://bugbountylibrary.com/r/blog%3Acorben-io-blog-17-11-27-tricky-cors.md).
- Plain CORS misconfig with no parsing mismatch: reflection on an authenticated profile API [E3](https://bugbountylibrary.com/r/h1%3A924951.md).
- Adjacent, not a CORS variant: extension background script proxying credentialed cross-origin POSTs for any content script, bypassing Site Isolation [E1](https://bugbountylibrary.com/r/blog%3Alf-lc-vrp-145304705.md).

## Impact and severity
Led to reading authenticated session preferences [E2](https://bugbountylibrary.com/r/blog%3Acorben-io-blog-17-11-27-tricky-cors.md), cross-origin reads of profile PII on click [E3](https://bugbountylibrary.com/r/h1%3A924951.md), and a Site Isolation bypass primitive [E1](https://bugbountylibrary.com/r/blog%3Alf-lc-vrp-145304705.md). Severity rises with credentials plus sensitive response fields; over-returned PII widens impact and often earns a bonus [E3](https://bugbountylibrary.com/r/h1%3A924951.md).

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Alf-lc-vrp-145304705.md
- E2: https://bugbountylibrary.com/r/blog%3Acorben-io-blog-17-11-27-tricky-cors.md
- E3: https://bugbountylibrary.com/r/h1%3A924951.md
