OFFAT OWASP

Architecture#

OFFAT-AI is a staged platform whose tools share one finding schema, one triager, and one interchange document (the Bundle). The uniformity is deliberate: a single AI triager and a single set of report writers serve the live platform pipeline and the source-only modes alike. The full platform design is in platform.md.

Shared finding schema#

Findings are JSON objects with the same core keys, so offat-triage and any downstream tooling work identically on either a live (DAST) or a source (SAST) finding:

{
  "id": "...", "vector_id": "sqli-error", "class": "sqli",
  "title": "...", "severity": "high", "cwe": "CWE-89", "owasp": "API8:2023",
  "endpoint": "ep-...",             // live finding (references an ASM endpoint)
  "file": "app.py", "line": 8,      // source finding
  "param": "q", "location": "query",
  "technique": "error", "payload": "'", "confidence": 0.85,
  "source_mode": "dast",            // dast | sast | graybox
  "evidence": { "status_code": 500, "matched_signature": "...", "snippet": "..." },
  "threat": { "owasp_api": "API8:2023", "owasp_web": "A03:2021", "cwe": "CWE-89" },
  "triage": { "verdict": "confirmed", "cvss": 7.5, "remediation": "...", "source": "ai" }
}

Platform pipeline (platform/ + engine-rs/)#

map --> prg --> threat-model --> test-gen --> execute --> triage --> report
Stage Where Responsibility
map platform (reuses graybox.graph_map, whitebox.hunt) endpoints (routes + OpenAPI/Swagger specs, params, response fields), sink/source inventory
prg platform.prg link response-field producers to request-param consumers (dataflow across endpoints)
threat-model platform.threat_model STRIDE threats, OWASP API Top 10 + CWE, risk, Mermaid DFD
test-gen platform.testgen injection vectors, PRG chains, identity-aware BOLA/BFLA/RBAC/auth/business cases
execute engine-rs (offat-engine) Rust async executor: HTTP/1.1+2, WebSocket and gRPC drivers (HTTP/3 opt-in), multi-identity requests + differential baseline, response capture
triage platform.consolidate + triager detect findings, attach threat mapping, triage (AI/heuristic)
report reporter (offat-report) SARIF / Markdown / HTML (with DFD) / compliance / PDF

Why Rust for the engine: the executor is an I/O-bound concurrent client where performance, memory safety and a single static binary matter. tokio + reqwest (rustls) drive HTTP/1.1 + HTTP/2; tokio-tungstenite drives WebSocket (ws/wss); tonic drives gRPC with a schema-less bytes codec (no .proto compilation); HTTP/3 + QUIC is an opt-in build feature (reqwest http3 -> h3 + quinn). Each case carries a protocol and is dispatched to the matching driver; a protocol the binary was not built with is recorded as skipped so the Bundle stays complete.

Source-only modes#

White-box pipeline (whitebox/, Python)#

recon --> code graph + patterns --> chain --> verify (triage / agent) --> report

The code graph proves source-to-sink flows and attaches routes; a dependency-free pattern hunter covers secrets, crypto and misconfiguration. External tools (syft, grype/trivy/osv-scanner, and opt-in semgrep) are used when present. verify uses the shared token-disciplined triager and the reporter emits SARIF code flows, JUnit and a --fail-on CI gate.

Gray-box pipeline (graybox/, Python)#

recon --> map endpoints --> code graph + patterns --> reachability --> analyze (AI) --> report

Fuses the source view with the mapped endpoint surface and judges each finding by reachability (which exposed endpoint reaches the sink). No live traffic. AI runs only on reachable findings - reachable-only, batched, cached and model-tiered.

Shared triager (triager/, Python)#

The triager enriches each finding with a verdict, CVSS and remediation, and carries the threat taxonomy (OWASP API Top 10 2023, OWASP Top 10 2021, CWE). It supports interchangeable backends behind one selection function (make_triager):

  • anthropic - the Anthropic Messages API (needs a key).
  • claude-code - shells out to the Claude Code CLI (claude -p).
  • codex - shells out to the OpenAI Codex CLI (codex exec).
  • heuristic - deterministic, offline, always available.

All use the same adversarial prompt (refute first) and fall back to the heuristic, so a run never fails and never requires a key. tiered_triage adds a content-hash verdict cache plus a cheap-model screen before a strong-model verify.

Extensibility#

  • New attack vector / test case: extend platform.testgen (vectors matched to params, or a new generator).
  • New source / sink / sanitizer: pass a --specs JSON file, or extend whitebox/offat_wb/cpg/specs.py; pattern-only rules live in whitebox/offat_wb/hunt.py.
  • New report format: add a writer in reporter/offat_report/render.py.
  • New threat mapping: extend triager/offat_triage/taxonomy.py.
  • Different AI backend: point OFFAT_AI_BASE_URL at an Anthropic-compatible endpoint, or set OFFAT_AI_MODEL.

Edit this page on GitHub