# Repo pre-scan bundle (ARION service)

One command, forty-one deterministic pre-scans, one consolidated
severity-tiered report. Built for the "quick honest surface check
before a release / vendor review / bounty submission" job.

**Honest scope:** this is a *pre-scan bundle*, not an audit. Every
wrapped tool is a line/manifest-level deterministic scanner — no
execution, no cloud/cluster access, no CVE feed. A FLAG means
"this line deserves human review"; a clean report is not proof the
repo is safe. Tool errors are reported as TOOL-ERROR rows, never
silently dropped.

## What runs (v23 — 42 tools)

| tool | surface |
|---|---|
| secret-prescan | committed keys, seed phrases, provider tokens |
| dep-prescan | manifest typosquats, unpinned/VCS deps, install scripts, missing lockfiles |
| ci-prescan | workflow injection, `pull_request_target` pwn-request, tag-pinned actions, permissions |
| docker-prescan | Dockerfile/compose: root, mutable bases, pipe-to-shell, secrets in ENV, privileged |
| crypto-prescan | MD5/SHA-1, DES/RC4/ECB, non-CSPRNG for secrets, TLS-verify-off, JWT none/weak |
| iac-prescan | Terraform + Kubernetes: world-open ingress, public buckets, privileged pods, literal secrets |
| auth-prescan | JWT alg-none/no-verify, disabled auth, weak password hashing, cookie flags |
| cors-prescan | reflected origin + credentials, wildcard+credentials, substring/suffix checks |
| csrf-prescan | explicit opt-outs, exception lists, mutating GET routes, SameSite=None, tokenless forms |
| sqli-prescan | interpolated/concatenated SQL into execute/query sinks, raw APIs, identifier positions |
| nosql-prescan | req-object operators, mass-assignment, $where/$function, prototype merge |
| xss-prescan | raw-HTML DOM sinks, string-eval, raw-template output, javascript: URLs |
| cmdi-prescan | request→exec sinks, shell wrappers, `shell=True`, pipe-to-shell |
| path-prescan | traversal, Zip Slip extraction, PHP LFI, upload-name paths, destructive sinks |
| ssti-prescan | request data in template source/name args across 15+ engines |
| redirect-prescan | open redirects, CRLF header injection, Host-header trust |
| xxe-prescan | unsafe XML parser defaults, external-entity opt-ins, DTD expansion |
| deser-prescan | pickle/unsafe yaml.load/ObjectInputStream/BinaryFormatter family |
| upload-prescan | upload validation gaps: exec-ext allow lists, client-mime trust, no size cap |
| injection-prescan | prompt-injection signatures in agent instruction files (SKILL.md/MCP/rules) |
| redos-prescan | catastrophic-backtracking regex: nested quantifiers, overlapping alternations, request-built patterns |
| authz-prescan | broken access control / BOLA: client-chosen role+identity, ownerless id-fetches, unguarded mutating/admin routes |
| jwt-prescan | token decoded-but-never-verified, none-alg, alg-confusion/unpinned verify, inline literal secrets, no-expiry tokens, URL/storage exposure, kid traversal |
| oauth-prescan | OAuth/OIDC flow: authorize URLs with no state, callbacks that never check state, request-sourced/loose-compared redirect_uri, implicit flow, missing PKCE, password grant, literal client secrets, tokens in query, plaintext-http endpoints |
| headers-prescan | response-hardening opt-outs: frame-protection off/clickjacking, CSP unsafe/wildcard sources, header strip, HSTS/nosniff disabled, powered-by, referrer unsafe-url, wildcard Permissions-Policy, public cache on session files |
| debug-prescan | debug-mode/info-disclosure: debug flags left on, stack traces & env dumps to the client, debug consoles/toolbars, Go pprof, Spring actuator exposure, display_errors, `?debug=` switches, stale breakpoints, PHP dump calls |
| clarity-prescan | Clarity/Stacks contract pre-scan: ungated value-moves & mints, as-contract drains, dynamic contract-call? targets, block-derived randomness, panic-unwraps, dropped call responses, config secrets |
| solidity-prescan | Solidity/EVM contract pre-scan: ungated fund-moves/mints/state-writes, call-before-write reentrancy, delegatecall targets, selfdestruct, tx.origin auth, unchecked call results, block-value randomness, spot-price reads, unguarded initializers, max approvals, balance-equality, ecrecover, secret literals |
| llm-prescan | LLM app integration: model output into exec/SQL/HTTP/HTML sinks, request input into authority-position prompts, secrets in prompt context, role-from-request, unbounded agent loops, model-chosen dispatch |
| graphql-prescan | GraphQL API: introspection/console/batching on, resolver input→exec/SQL/HTTP, mutation auth gaps, missing depth/complexity limits |
| ws-prescan | WebSocket/realtime: unchecked-origin acceptors (CSWSH), explicit wildcard/always-true origin bypasses, socket message→exec/SQL/HTTP, unfiltered re-broadcast, no-auth/no-frame-limit acceptors, plaintext ws:// |
| session-prescan | session/cookie security: HttpOnly/Secure/SameSite off, fixation, trans-sid, tokens in storage/URL, long lifetimes, literal secrets, wide domains |
| tls-prescan | transport security: cert verification off (verify=False, CERT_NONE/VERIFY_NONE, rejectUnauthorized, InsecureSkipVerify, trust-all managers), hostname checks off, legacy protocol pins (SSLv3/TLSv1.x), broken cipher classes in suite strings, http:// in transport positions, db connection strings with TLS off, package-manager TLS bypasses, IaC skip-verify keys, legacy wrap_socket contexts |
| timing-prescan | timing-attack shapes: early-exit `==`/`.equals()`/`strcmp` compares on secret-named operands, non-constant-time library compares (bytes.Equal/Arrays.equals/SequenceEqual), prefix & membership probes, hand-rolled comparator loops, length oracles, raw token DB lookups — two-tier secret-name model with auth-context gating |
| memsafe-prescan | C/C++/Objective-C memory safety — gets(), scanf without field width, unbounded strcpy/sprintf families (severity tiered by declared destination size), literal overruns, non-literal format strings, strncpy truncation, stack-array returns, unchecked alloc, double free, mktemp, alloca, realloc-self, banned calls — size-aware declaration model |
| log-prescan | sensitive data into logs (CWE-532/117) — secrets/credentials/session material/PII/env dumps/request objects/body data into logger + stdout sinks; literal-label stripping, mask/metadata-suffix/presence-check suppression, auth-header reads HIGH, subscripted headers LOW |
| proto-prescan | JS/TS prototype pollution (CWE-1321/915) — __proto__/constructor.prototype writes, attacker-derived _.set paths, request-fed merges, unguarded hand-rolled deep merges, deep-merge lib sinks, Object.assign over request sources, unguarded key-enumeration copies, request-object spreads, file-level no-guard note |
| race-prescan | TOCTOU / check-then-act races (CWE-367) — exists/access/stat checks paired to file ops on the same identifier, symlink-swap races, non-atomic lockfile/pidfile acquisition, dir-create races, non-atomic DB check-then-insert; atomic-fix + reassignment + lock-context suppression |
| webconf-prescan | nginx + Apache config misconfiguration (CWE-16) — alias-slash traversal, satisfy-any, open proxy, DAV, root grants, CGI under uploads, weak TLS, header spoofing, CORS; sibling-subtree-isolated block model |
| mcp-prescan | MCP configs + tool registration (tool-poisoning) — description injection/exfil, secret passthrough, unpinned remote packages, plaintext/no-auth endpoints, wildcard/write auto-approve, scope, binds, shadowing |
| ssrfsink-prescan | SSRF dataflow (CWE-918) — request-taint into HTTP/scheme-capable fetch sinks across 8 languages; weak substring/prefix-domain guards; redirect-follow, DNS-rebinding, decode-then-fetch, blind-SSRF url-param storage |
| reslimit-prescan | unbounded resources (CWE-770/400) — request-derived size into alloc/read/loop-bound/pagination/delay sinks across 11 languages; numeric-cast taint, call-derived MEDIUM tier, bound-guard + literal-reassign suppression, shell size-arg extraction |

Opt-in: `--html` additionally runs md-prescan over `*.html` files.
Not wrapped (different target type): ssrf-prescan (live URL) and the
EVM/Solana token-security snapshots (live chain) — see those listings.

## Usage

```
python3 repo_prescan_bundle.py <repo-dir> [-o report.md] [--json]
                                [--html] [--tools name,name]
                                [--tools-dir DIR]
```

- Exit 0 = no HIGH/MEDIUM findings, 1 = findings, 2 = usage error.
- `--json` emits machine-readable output for CI gates.
- `--tools` selects a subset (e.g. `--tools xss-prescan,sqli-prescan`).
- The runner self-locates the sibling tools under `deliverables/`
  (or `--tools-dir`); each tool also works standalone.

## Sample

`sample-report.md` is the verbatim output over a real
service repo (node/postgres API with Docker + GitHub Actions +
compose): all 38 tools ran clean and produced 17 HIGH / 89 MEDIUM \
195 LOW, including a literal `POSTGRES_PASSWORD`, a
`rejectUnauthorized: false` DB pool (also caught by tls-prescan),
`pull_request_target` + tag-pinned actions, 2 dynamic-SQL
constructions, a `dangerouslySetInnerHTML` sink, 32 CSRF-tokenless
mutating forms, and a hardcoded `client_secret !==` literal compare
(timing-prescan).
That is the entire artifact — what you see is exactly what you get.

## Pricing

5000 sats (~$5) per repo run — one consolidated report, all
thirty-eight scanners (v1 six-tool bundle was 3000 sats; v19 is 6x+
coverage). Single-surface scans remain 300 sats each. Delivered as
signed markdown + ACR-1 receipt on request.
