| name | sast-scan |
| description | Produces a SAST-FINDINGS.md (static security + secret findings over your OWN code, each reproduced, with remediation) after a blocking authorization+ownership check. Use to statically scan owned code for vulnerabilities and secrets, defensively. |
sast-scan
The static-analysis producer of the security-testing pack (D5, opt-in). It scans your own authorized
code for security weaknesses and committed secrets, reproduces each finding, and writes a
SAST-FINDINGS.md — findings paired with severity and remediation. It is defensive: the deliverable is a
findings-and-fix report over an asset you own, never a reusable exploit. Authorization plus ownership of the
code is the blocking precondition — no owned scope, no scan.
Findings verify by Audit (is each finding real, reproduced, traceable, remediable?). When no scanner
binds, the scan degrades to a Review-mode manual pass and records the automated coverage as NOT-RUN — it
never reports "clean" for a scan that did not run.
What this does / does not do
Does: confirm authorization + ownership first (blocking); resolve the security-scan capability through the
tool seam; run the scanner over the owned code; reproduce each candidate finding before reporting; redact
secrets in the report; write SAST-FINDINGS.md with severity + remediation owner per finding + stated
coverage; write a receipt. Does not: touch code it does not own or is not authorized for, report an
unreproduced candidate as a real finding, print a discovered secret in the clear, emit a reusable
exploit/payload, or claim clean coverage for an unrun scanner.
When NOT to use
- No confirmed authorization + ownership of the target code — that is blocking; stop and get it, do not scan.
- The request is to test a running app's attack surface — that is
product-pentest; or to probe an AI model
— that is ai-red-team. This sub_target is static analysis over source.
- The ask is to produce a weaponized artifact (a working exploit, a bypass, an obfuscated payload) — refuse;
the ai + security gates reject it regardless of framing.
- The work is auditing controls/design rather than scanning code for weaknesses — that is
security-review.
Reference Routing
| Situation | Reference |
|---|
| Thin inputs / no scanner / weaponization ask | rules/cold-start.md |
| The scanner backend (capability resolution, degrade) | engine/tools/tool-resolve.py resolve security-scan |
| Per-sub_target must-declares · overlay · vocabulary | ../acceptance/sub-targets.md · ../acceptance/overlay.md · ../vocabulary.md |
| Sibling sub_targets (running app / AI model) | product-pentest · ai-red-team |
Inputs
- The owned codebase + the authorization/ownership evidence (system, boundary, sign-off).
- The ruleset/scanner to use (resolved via the
security-scan capability) and the finding classes in scope.
- The security-testing pack (
../vocabulary.md, ../acceptance/) + state/intake.json.
How to do it
- Authorization + ownership (blocking). Confirm the requester owns/controls the code and has authorized
the scan — system, boundary, sign-off, evidence. Without it, stop and record the gap; no owned scope, no
scan.
- Scope the surface. State what code is in scope, what is out, and which finding classes (injection,
secrets, unsafe deserialization, weak crypto, …) the scan targets. Non-destructive: reading code only.
- Resolve the scanner. Ask the tool seam for the
security-scan capability. If a scanner binds, run it
over the in-scope code. If none binds, degrade to a manual Review pass and mark the automated coverage
NOT-RUN — never fabricate "clean".
- Reproduce every candidate. A scanner hit is a candidate, not a finding. Reproduce it (trace the data
flow / confirm the sink is reachable) before it is reported; an unreproduced candidate is a hypothesis,
recorded separately, not a real finding.
- Redact + rate. Redact any discovered secret in the report (reference its location, never its value).
Give each finding a severity and a remediation owner; a finding with neither is an alert, not a closed
item.
- State coverage. What was scanned, what was not, and the false-positive posture — coverage is part of
the deliverable, not an afterthought.
- Write
SAST-FINDINGS.md — findings (reproduced) + remediation + coverage; hypotheses listed apart.
Gate (before marking complete)
A gate failure is fixed before lock, not waived — these mirror the authorization/security/testing gates.
Output
- SAST-FINDINGS.md at the product root (or
security-test/SAST-FINDINGS.md if that dir exists) —
persistence: Spec-Anchored. Authorized scope · findings (reproduced, severity, remediation owner) ·
redacted secrets · coverage · unreproduced hypotheses (separate).
- receipt (
<workspace>/receipts/sast-scan-receipt-<ts>.json): base schema + sub_target,
authorization_confirmed, scope, scanner_backend, findings_count, secrets_redacted,
coverage, findings_path, gate_checks. persistence: Spec-Anchored.
Completion Criteria
Done when: authorization + ownership were confirmed (blocking), the owned code was scanned (or the
absence recorded NOT-RUN), every reported finding was reproduced, secrets are redacted, each finding has a
severity + remediation owner, coverage is stated, and a receipt records the gate checks — the deliverable is
a defensive findings report.
Not done if: any scan ran without confirmed authorization/ownership; an unreproduced candidate is reported
as a finding; a secret is printed in the clear; a reusable exploit was produced; or an unrun scanner is
reported as "clean".
Next step: remediation owners fix the findings; a re-scan confirms closure. product-pentest covers the
running app's attack surface; ai-red-team covers an AI model.
Related Skills
- product-pentest / ai-red-team: sibling security-testing sub_targets — the running app's attack
surface / an owned AI model.
sast-scan is static over source.
- security-review: audits controls + design (defensive review).
sast-scan actively scans owned code for
weaknesses; the review reasons about the controls around it.
- verifier: Audits the findings (real / reproduced / remediable) and honors the NOT-RUN when no scanner
bound — it never fabricates a clean scan.