# Auth/session misconfiguration pre-scan (ARION service)

Deterministic scanner for authentication and session-handling bug
classes in source files. No server, no runtime, no network — works
fully offline on the code.

**Honest scope:** this is a *pre-scan*, not an audit. Files are read
line-wise with light per-call lookahead (multi-line cookie options are
joined before flag checks) — it cannot see middleware order,
route-level overrides, runtime config, or reachability. A FLAG means
"this deserves human review"; a clean report is not proof the auth
layer is safe.

## Coverage

- **`AUTH-JWT-NONE-ALG` (HIGH)** — JWT `none` algorithm accepted or
  selected (`algorithms=["none",…]`, `algorithm: "none"`, `allowNone`,
  `Algorithm.none`). Unsigned tokens treated as valid.
- **`AUTH-JWT-NOVERIFY` (HIGH/LOW)** — signature verification
  explicitly disabled: `verify=False`, `verify_signature: false`,
  ruby `JWT.decode(t, nil, false)`, `verify_jwt = False`,
  `skipVerification`. Bare `jwt.decode()` in JS/TS is LOW — decoded
  claims are unverified; a `verify()` must precede authz decisions.
- **`AUTH-PW-WEAKHASH` (HIGH)** — md5/sha1 applied to a
  password/credential (hashlib, crypto.createHash,
  `MessageDigest.getInstance`, PHP `md5($password)`, `hash('md5',…)`,
  `Digest::MD5`). Salted-KDF lines (bcrypt/argon2/scrypt/pbkdf2,
  `password_hash`, `make_password`, passlib…) are suppressed.
- **`AUTH-PW-FASTHASH` (MEDIUM)** — single-pass sha256/384/512 applied
  to a password — still brute-forceable; use a salted KDF.
- **`AUTH-JWT-SECRET-LIT` (MEDIUM)** — `jwt.sign`/`jwt.verify` with an
  inline literal secret, `Keys.hmacShaKeyFor("…")`,
  `new SecretKeySpec("…")`.
- **`AUTH-PW-HARDCODED` (MEDIUM)** — credential compared to a
  hardcoded quoted literal (`if password == "s3cret"`).
- **`AUTH-DISABLED` (MEDIUM/LOW)** — auth explicitly switched off:
  DRF `permission_classes=[AllowAny]`, ASP.NET `[AllowAnonymous]`,
  `@Public()/@SkipAuth/@NoAuth`, `auth:false` / `auth=null` route
  flags, `skip_auth`/`bypass_auth`/`disable_auth` enablers, auth-stub
  that unconditionally returns `true`. Commented-out auth decorators
  (`# @login_required`) are LOW.
- **`AUTH-PREDICTABLE-TOKEN` (MEDIUM)** — non-CSPRNG minting a
  token/session/reset/nonce/otp value: `Math.random`, `rand`,
  `mt_rand`, `random.*`, `new Random`, `uniqid`, `srand`.
  `secrets.`/`crypto`/urandom/SecureRandom lines suppressed.
- **`AUTH-SESSION-FIXATION` (MEDIUM)** — session id taken from request
  input (`session_id($_GET[…])`, `req.session_id = req.query.sid`).
- **`AUTH-COOKIE-FLAGS` (MEDIUM/LOW)** — session/auth cookie set
  without `HttpOnly` (MEDIUM); `HttpOnly` present but `Secure` and/or
  `SameSite` missing (LOW). Multi-line options objects are joined
  before checking.
- **`AUTH-TIMING-COMPARE` (LOW)** — credential material compared with
  `==`/`!=`/`.equals()` — byte-wise timing leak; use
  `hmac.compare_digest` / `crypto.timingSafeEqual`. Null/empty/numeric
  comparisons and timing-safe helpers suppressed.
- **`AUTH-LOCALSTORAGE-TOKEN` (LOW)** — token/session/jwt written to
  `localStorage`/`sessionStorage` — script-readable (XSS).
- **`AUTH-JWT-NO-EXP` (LOW)** — single-line `jwt.sign` without
  `exp`/`expiresIn`/`maxAge` — tokens that never expire.
- **`AUTH-BASIC-INLINE` (LOW)** — hardcoded
  `Authorization: Basic <b64>` literal.

Targets: `.js .jsx .ts .tsx .mjs .cjs .py .rb .go .java .kt .php .cs
.rs .ex .exs`. Skips `node_modules`, `vendor`, `dist`, `build`,
`target`, VCS, cache, and test/spec/fixture dirs.

## Usage

```
python3 auth_prescan.py <file-or-dir> [--json]
python3 auth_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.
