codaprobe: live app testing

codaprobe tests a live application over the network, only on targets a scope file authorises; any ambiguity in the scope means refusal.

Before any packet leaves, the target must be on the scope's allowlist. That is why this guide starts with authorisation.

Licence. In the public binary, codaprobe needs a Pro, Verified or Platform licence (Vibe does not include runtime). Without one it exits with code 40 (3 is a scope refusal). check-scope, schema and verify-audit stay free. Before launch no licence is accepted yet: the public binary exits 40 even with a token. See plans.

1. Authorisation and scope (read before running)

The scope is a JSON file declaring who authorised and what is authorised:

{
  "authorization": {
    "attestation": "authorised pentest — ticket SEC-4210, approved by Maria Silva (CISO) on 2026-07-20",
    "granted": true
  },
  "entries": [
    { "host": "app.customer.test", "port": 443, "path_prefix": "/api", "mutating_opt_in": false }
  ]
}
FieldMeaningIf wrong
attestationfree-text provenance (who, ticket, date); goes into the reportthe report loses its value as evidence
grantedthe operator declares the authorisation; absent = falseeverything is refused
host · porttarget in canonical form, explicit portnon-canonical form fails loading; a different port is refused
path_prefixprefix matched on whole segments (/api covers /api/x, not /apix); requireda misspelt key fails loading instead of authorising the whole host
mutating_opt_inallows POST/PUT/PATCH/DELETE on this target; absent = falsemutating methods are refused before the network

An unknown field fails loading: a typo cannot become permission. Check without touching the network:

codaprobe check-scope --scope scope.json --url https://app.customer.test/api/

2. Scan

# passive — legitimate traffic only, no payloads (headers, cookies, CORS, leaks)
codaprobe scan --scope scope.json --url https://app.customer.test/api > report.json

# active, driven by the contract (OpenAPI 3 JSON/YAML, Postman collection or HAR)
codaprobe scan --scope scope.json --url https://app.customer.test/api \
  --contract openapi.yaml --active --auth-file auth.txt --audit-out audit.json > report.json

# no contract: discover the surface by browserless crawl
codaprobe scan --scope scope.json --url https://app.customer.test --crawl --active > report.json

# GraphQL from introspection
codaprobe scan --scope scope.json --url https://app.customer.test/graphql --graphql introspection.json --active

Active mode tests query, header, cookie, form, path segment and the parameter name. Payloads are benign: they reveal the flaw without exploiting it. For flaws with no visible response there is --temporal; out-of-band detection (--oob) is off by default.

Flags that change the result: --rps <n> (total rate, default 5), --concorrencia <n> (concurrency), --fail-on <sev> (fails only on confirmed findings), --ca-cert <pem> (prefer it over --insecure, which also disables hostname checking), --correlate-src <envelope> (cross-matches with the codafort envelope).

3. The report and the audit log

The report is coda-dast/1: moment: run findings, redacted URL (no userinfo, no query), the authorisation text and the audit log anchor. The audit log (--audit-out) is SHA-256-chained and is checked like this:

codaprobe verify-audit --file audit.json --report report.json    # exit 0 INTACT · 21 TAMPERED

With --report (or --expect-anchor), the command checks the log against the anchor in the report and answers INTACT (exit 0) or TAMPERED (exit 21). Without them, the best possible verdict is CONSISTENT: whoever edits the log can recompute the chain, and only the anchor in the report catches a removal with the chain rebuilt. Always verify with the report.

4. In the pipeline

codaprobe scan --scope scope.json --url "$TARGET" --contract openapi.yaml --active \
  --auth-file auth.txt --rps 10 --fail-on high --audit-out audit.json > report.json

Only a confirmed finding fails the build; a candidate does not.

ExitMeaning
0ran (findings are not errors)
1--fail-on failed
3target refused by scope
20invalid input (scope, contract, credential, absurd --rps)
21verify-audit: broken chain or anchor mismatch
30I/O or network error at start
40no licence (see above)

What it never does

It never relaxes scope, non-destructive mode or URL redaction to find more. It keeps no secrets in the report.