CORS misconfiguration scanner that actually checks if a vulnerability is exploitable before flagging it.
Most CORS scanners see a reflected Origin header and immediately scream "VULNERABLE!" — but that's usually a false positive. If there's no Access-Control-Allow-Credentials: true, or if auth is token-based instead of cookies, the browser won't let an attacker do anything with it.
CORSbuster runs 12 different CORS checks, then puts each finding through a 3-stage verification pipeline: detect → verify credentials → check if the response actually contains sensitive data. Only then does it classify severity.
╭──────────────────────────────────────────────────────────────────────╮
│ CORSbuster v1.2.0 — CORS Misconfiguration Scanner │
│ Targets: 1 | Threads: 3 | Timeout: 10s | STEALTH MODE │
╰──────────────────────────────────────────────────────────────────────╯
[!!!] Reflected Origin | https://target.com/api/users/1
Origin: https://evil.com → ACAO: https://evil.com
Credentials: true | Sensitive data: email, user_data | EXPLOITABLE
[!] Null Origin | https://target.com/api/users/1
Origin: null → ACAO: null
Credentials: true | EXPLOITABLE
[i] Wildcard ACAO | https://target.com/api/users/1
Credentials: false
Scan complete in 28.0s | Targets: 1 | Checks: 12
Findings: 7 CRITICAL 1 HIGH 2 MEDIUM 1 LOW
That last one (Wildcard ACAO) — other tools flag it as vulnerable. We don't, because there's no credentials header. Browser won't send cookies. Not exploitable.
# one-liner
curl -sSL https://raw.githubusercontent.com/CyberWarrior9/corsbuster/main/install.sh | bash
# or manually
git clone https://github.com/CyberWarrior9/corsbuster.git
cd corsbuster
pip install -e .The installer checks what dependencies you already have and only installs what's missing.
# basic scan
corsbuster -u https://target.com/api/endpoint
# scan with your session cookie (needed to test authenticated endpoints)
corsbuster -u https://target.com/api/me -H "Cookie: session=abc123"
# stealth mode — slow but won't get your IP blocked
corsbuster -u https://target.com --stealth
# bruteforce directories first, then CORS scan everything found
corsbuster -u https://target.com -b --stealth
# discover common API paths (/api/user, /graphql, etc) and test each
corsbuster -u https://target.com --discover
# crawl the site, pull endpoints from HTML + JS files, test each
corsbuster -u https://target.com -c --depth 3
# pipe URLs from other tools
waybackurls target.com | corsbuster
subfinder -d target.com | httpx | corsbuster --poc
cat urls.txt | corsbuster -o report.json
# enumerate subdomains, test each for CORS
corsbuster -u https://target.com --subdomains --stealth
# pull historical endpoints from Wayback Machine
corsbuster -u https://target.com --wayback
# test CORS on POST/PUT/DELETE too, not just GET
corsbuster -u https://target.com --methods
# scope control — only scan target.com, skip static files
corsbuster -u https://target.com -b --scope target.com --exclude "*.css" --exclude "/static/*"
# resume an interrupted scan
corsbuster -u https://target.com -b --stealth --resume
# go all in — one command, full auto
corsbuster -u target.com --subdomains --wayback --discover -b -c --methods --stealth --poc -o report.json
# silent mode — just exploitable findings, tab-separated (for scripting)
corsbuster -u https://target.com -s
# through burp proxy
corsbuster -u https://target.com -x http://127.0.0.1:808012 CORS checks in total:
- Reflected Origin — does the server just echo back whatever
Originyou send? - Null Origin — does it accept
Origin: null? (exploitable via sandboxed iframes) - Pre-domain Bypass — does
evilexample.compass the check? - Post-domain Bypass — does
example.com.evil.compass? - Subdomain Wildcard — does
evil.example.comget through? - Unescaped Dot — regex dot not escaped, so
exampleXcomworks - Special Characters — backtick, underscore and other chars that break parsers
- HTTP Origin Trust — HTTPS site trusts HTTP origins (MITM risk)
- Third-party Origins — trusts github.io, netlify.app, etc
- Wildcard ACAO —
Access-Control-Allow-Origin: * - Substring Match — partial domain matching
- Include Match — domain as substring gets accepted
This is the main thing that makes CORSbuster different.
Stage 1 — Detection: Send crafted Origin headers. Before that, send a baseline request without any Origin to see what the default ACAO looks like. If a reflected origin matches the baseline, it's static config, not a vulnerability. Also sends a second different origin to confirm dynamic reflection.
Stage 2 — Credential check: No Access-Control-Allow-Credentials: true? Then the browser won't send cookies cross-origin. Max severity = INFO. Done.
Stage 3 — Impact assessment: If credentials ARE allowed, we scan the response body for sensitive stuff — emails, API keys, JWTs, password fields, PII patterns. We also check HOW the user is authenticated: cookie-based auth is exploitable (browsers auto-send cookies), but Bearer token auth is NOT (browsers don't auto-send Authorization headers cross-origin).
Only when all three stages confirm real exploitability do we flag it as CRITICAL and generate a PoC.
CRITICAL — attacker can steal authenticated data right now
HIGH — credentials present, data likely sensitive in other contexts
MEDIUM — needs a second vuln to chain (subdomain XSS, etc)
LOW — needs MITM or browser blocks it
INFO — misconfigured but not exploitable
Real targets have WAFs. Running hundreds of requests at max threads with a scanner User-Agent will get you blocked instantly.
--stealth fixes that:
- Uses a real Chrome User-Agent
- Drops to 3 concurrent threads
- Adds random delays (0.5-3s) between requests
- Auto-detects 429 rate limiting and backs off exponentially
# this will probably get you blocked
corsbuster -u https://target.com -b
# this won't
corsbuster -u https://target.com -b --stealthEven without --stealth, the default User-Agent is a real browser string (not a scanner fingerprint).
-b tests ~800 common paths against the target. If you give it a URL with a path like https://target.com/app/api, it bruteforces BOTH:
https://target.com/(base domain)https://target.com/app/api/(your path)
Then combines all found endpoints and runs CORS checks on everything.
Covers common API routes, admin panels, config files, framework-specific paths (WordPress, Laravel, Django, Spring, etc), sensitive files, and auth endpoints.
Accepts 200, 301/302, and 403 as "endpoint exists" — because CORS headers sometimes leak even on forbidden endpoints.
--subdomains queries crt.sh (certificate transparency logs) to find all subdomains of a target, checks which ones are alive, and adds them to the scan. No external tools needed.
--wayback pulls historical URLs from web.archive.org. Finds deleted pages, old API endpoints, forgotten admin panels — stuff that's often still live but not linked anywhere. Filters out static files automatically.
By default we only test GET. --methods also tests POST, PUT, DELETE, and PATCH — because some servers have different CORS rules per method. Also runs an OPTIONS preflight check and flags if dangerous methods (PUT/DELETE) are allowed cross-origin.
When CORSbuster finds a dynamically reflected Access-Control-Allow-Origin, it checks if the Vary: Origin header is present. If it's missing and a CDN/cache is detected (via x-cache, cf-cache-status, etc), it flags a cache poisoning risk — an attacker could poison the cache with their origin.
Stay in scope during large scans:
# only scan URLs on target.com
corsbuster -u https://target.com --subdomains -b --scope target.com
# skip certain paths
corsbuster -u https://target.com -b --exclude "*.css" --exclude "/static/*" --exclude "*robots*"Long scans can be interrupted (ctrl+c) and resumed later. CORSbuster saves a checkpoint file and skips already-scanned URLs.
corsbuster -u https://target.com -b --stealth --resume- Terminal — color-coded findings as they come in
- JSON (
-o report.json) — structured report - HTML (
--html-report report.html) — standalone dark-themed report you can share - PoC HTML (
--poc) — working exploit file per vulnerability. For null origin vulns it uses the sandboxed iframe technique - Silent (
-s) — tab-separatedURL\tSEVERITY\tCHECK, for piping into other tools
0— nothing critical2— CRITICAL or HIGH findings detected (useful for CI/CD)
Python 3.8+ with aiohttp, rich, tldextract (installed automatically).
For authorized testing only. Get permission before scanning anything you don't own.
MIT