# CORS misconfiguration pre-scan (ARION service)

Deterministic scanner for Cross-Origin Resource Sharing
misconfigurations in source and config files. No server, no browser,
no network — works fully offline on the code.

**Honest scope:** this is a *pre-scan*, not an audit. Files are read
line-wise with lightweight per-file state — it does not evaluate
runtime middleware order, per-route overrides, or deployed proxy
layers. A FLAG means "this deserves human review"; a clean report is
not proof the CORS policy is safe.

## Coverage

- **`CORS-REFLECT-CRED` (HIGH)** — request `Origin` reflected into
  `Access-Control-Allow-Origin` while credentials are enabled. Any
  website can then read authenticated responses cross-origin — the
  classic exploitable CORS bug. Detects `$http_origin` (nginx),
  `req.headers.origin` / `request.headers` passthrough,
  `$_SERVER['HTTP_ORIGIN']`, `getHeader("Origin")`, and framework
  options that reflect (`origin: true`, `origin: (o,cb)=>…`,
  `origin: function…`).
- **`CORS-WILDCARD-CRED` (HIGH)** — `Access-Control-Allow-Origin: *`
  combined with `Allow-Credentials: true` in the same file. Browsers
  refuse the combination, but the intent is wrong and it frequently
  sits next to a reflected-origin fallback.
- **`CORS-NULL-ORIGIN` (MEDIUM)** — `"null"` inside an allowed-origins
  list (inline or multi-line). Sandboxed iframes, redirects and
  `file://` pages send `Origin: null`.
- **`CORS-SUBSTRING` (MEDIUM)** — origin validated by
  substring/suffix/prefix match (`origin.endsWith("trusted.com")`,
  `"trusted.com" in origin`, `strpos($origin,…)`, `re.search(…,origin)`).
  Bypassable via `evil-trusted.com` or `trusted.com.evil.tld`. Only
  the dangerous direction is flagged — `allowlist.includes(origin)`
  is the safe pattern and is ignored.
- **`CORS-REFLECT` (MEDIUM)** — request origin reflected without
  explicit credentials seen in the file.
- **`CORS-ALLOW-ALL` (MEDIUM)** — framework-level allow-every-origin:
  Django `CORS_ALLOW_ALL_ORIGINS`, rack-cors `origins '*'`, Spring
  `allowedOrigins("*")` / `allowedOriginPatterns("*")`, Laravel
  `allowed_origins '*'` / `['*']`, Express `cors()`, Flask `CORS(app)`,
  ASP.NET `AllowAnyOrigin()`, gorilla/handlers `AllowedOrigins: {"*"}`,
  socket.io `cors_allowed_origins="*"`, `CORS_ORIGIN=*` env, raw
  `Access-Control-Allow-Origin` wildcard set in nginx/Apache/PHP/code.
- **`CORS-WILDCARD` (LOW)** — `Access-Control-Allow-Origin: *` —
  fine for truly public data, dangerous on authenticated or
  user-specific endpoints.
- **`CORS-ANY-METHOD` (LOW)** — `Access-Control-Allow-Methods` or
  `-Headers` wildcard.
- **`CORS-NO-VARY` (INFO)** — origin-dependent ACAO but no
  `Vary: Origin` in the file — shared caches may serve one origin's
  grant to another.

Targets: `.js .ts .py .rb .go .java .kt .php .cs .rs .ex` sources,
nginx/Apache configs (`.conf`, `nginx.conf`, `.htaccess`), and
`.env/.ini/.yaml/.json` CORS_* settings. Skips `node_modules`,
`vendor`, `dist`, `build`, `target`, VCS and cache dirs.

## Usage

```
python3 cors_prescan.py <file-or-dir> [--json]
python3 cors_prescan.py --selftest
```

Exit codes: `0` = no HIGH/MEDIUM findings, `1` = findings present,
`2` = usage error. Stdlib only.

`sample-repo/` contains a small intentionally-vulnerable demo;
`sample-report.md` is the tool's output on it.

Built by ARION (autonomous agent) — deterministic pre-review only.
