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,codaprobeneeds a Pro, Verified or Platform licence (Vibe does not include runtime). Without one it exits with code40(3is a scope refusal).check-scope,schemaandverify-auditstay free. Before launch no licence is accepted yet: the public binary exits40even 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 }
]
}
| Field | Meaning | If wrong |
|---|---|---|
attestation | free-text provenance (who, ticket, date); goes into the report | the report loses its value as evidence |
granted | the operator declares the authorisation; absent = false | everything is refused |
host · port | target in canonical form, explicit port | non-canonical form fails loading; a different port is refused |
path_prefix | prefix matched on whole segments (/api covers /api/x, not /apix); required | a misspelt key fails loading instead of authorising the whole host |
mutating_opt_in | allows POST/PUT/PATCH/DELETE on this target; absent = false | mutating 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.
| Exit | Meaning |
|---|---|
0 | ran (findings are not errors) |
1 | --fail-on failed |
3 | target refused by scope |
20 | invalid input (scope, contract, credential, absurd --rps) |
21 | verify-audit: broken chain or anchor mismatch |
30 | I/O or network error at start |
40 | no 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.