Capability: contract:scan-format
Kind: interface
Vendor: agnostic
A scan-format adapter teaches security-issue-import-from-scan how to read one security scanner‘s report layout. The skill is scanner-agnostic; everything format-specific — how to recognise a scan folder, how to enumerate findings, how to pull a finding’s evidence, and how to normalise the fields — lives behind this contract so the triage flow is identical across scanners.
A scan is a set of findings produced by one run of a security scanner against a target at a specific commit. It is materialised as a scan folder (in the reference adopter, a directory under apache/tooling-agents/ASVS/reports/.../<commit>/) and/or referenced from a tracking GitHub issue. A scan folder always carries two things the contract below maps to:
| Adapter | Recognises | Index file | Evidence file |
|---|---|---|---|
asvs (reference) | a dir holding both files below | issues.md (## Issue: FINDING-NNN - <title> blocks) | consolidated.md (#### FINDING-NNN: <title> sections with an attribute table + Description + Remediation) |
An adapter implements (as documented behaviour, not a code API):
detect(folder) -> adapter_name | nullReturn the adapter name if folder is a scan folder this adapter understands (for asvs: it contains both issues.md and consolidated.md), else null. Used for recursive discovery: the skill walks a parent folder / git tree and calls detect on each directory, processing every match.
finding_index(folder) -> [finding]Parse the index file into a list of findings, each normalised to the finding schema below. This is the enumeration pass; it does not need the deep evidence.
evidence(folder, finding_id) -> {detail, code_refs, reachability, remediation}Parse the evidence file for one finding: the full description, the cited file paths + lines, the reachability / PoC reasoning, and the proposed fix. This is the load-bearing read — the skill's Step B classifies from this, not from the index summary.
Every adapter normalises a finding to:
| Field | Meaning |
|---|---|
id | stable per-scan identifier (e.g. FINDING-001) |
title | one-line description |
severity | the scanner's severity label (treated as a hypothesis, not a verdict) |
level | scanner rigor level, if any (e.g. ASVS L1/L2/L3) |
cwe | CWE id(s), if cited |
files | affected file paths (+ lines where given) |
attacker_capability | what the attacker must already have — the load-bearing input for the trust-boundary mapping |
impact | claimed impact |
remediation | the scanner's proposed fix |
The skill treats severity/level as starting hypotheses and re-derives the real disposition from the project's Security Model + precedents.
The adopter declares, in <project-config>/project.md:
apache/tooling-agents);asvs).security-issue-triage); the adapter only reads findings, it never decides them.security-issue-import-from-scan — the consumer.tools/forwarder-relay/README.md — a sibling pluggable-adapter contract this one mirrors.