CORS (Cross-Origin Resource Sharing) is one of the most misunderstood security features. A misconfigured CORS turns a browser into a free data-exfiltration proxy for any site that visits your API. Here's how to audit it passively — no exploits, just reading headers.
The three deadly patterns
-
Origin reflection: the server echoes
Access-Control-Allow-Origin: <whatever the browser sent>instead of an allow-list. Any malicious site can read responses with the victim's cookies (ifAccess-Control-Allow-Credentials: true). -
Wildcard + credentials:
Access-Control-Allow-Origin: *combined with credentials is rejected by modern browsers (good), but servers doing reflection with credentials are worse — the browser does accept those. -
null origin: sandboxed iframes and some redirects send
Origin: null; naive servers allow it.
The passive check
Send a normal GET with a hostile Origin header and inspect the response:
curl -sI -H "Origin: https://evil.example.com" https://api.target.com/me
Findings to flag:
-
Access-Control-Allow-Origin: https://evil.example.com→ FAIL (reflection) -
Access-Control-Allow-Credentials: true+ reflected origin → FAIL (authenticated data leak) -
Access-Control-Allow-Origin: *(no credentials) → WARN (non-authenticated data readable by any origin)
My CLI reconpp runs both probes (Origin: https://evil.example.org and Origin: null) automatically, together with headers/TLS/cookies/сookie checks:
pip install git+https://github.com/bryanrafaelbueno/reconpp
reconpp -u https://api.target.com -f md -o relatorio.md
The fix
- Allow-list trusted origins explicitly — never echo the Origin header
- Don't use
*with credentials; don't reflectnull - Vary on Origin when the resource is shared
Full 70+ point audit checklist (headers, TLS, sessions, API, auth, CI/CD) in my pt-BR ebook — free sample at the store:
- Store (Pix): https://bryanrafaelbueno.github.io/audit-br-store/
- Free sample PDF: https://bryanrafaelbueno.github.io/audit-br-store/sample.pdf
Top comments (0)