SARIF output
--format sarif writes SARIF 2.1.0, the standard format code-scanning tools read.
vulkro-sf scan . --format sarif > vulkro-sf.sarif
vulkro-sf antipatterns . --format sarif > antipatterns.sarif
Upload it to GitHub Code Scanning (github/codeql-action/upload-sarif), keep it as a CI artifact, or open it in any SARIF viewer.
Shape
One result per finding, with the rule id, level, message and location. The rules that ran are listed in tool.driver.rules, each with a short description and a helpUri.
{
"version": "2.1.0",
"runs": [{
"tool": {"driver": {"name": "vulkro", "rules": [ ... ]}},
"results": [{
"ruleId": "apex-dyn-exec-soql",
"level": "note",
"message": {
"text": "Dynamic-execution primitive `Database.query` runs a runtime-assembled (non-constant) query string. ...",
"markdown": "**Dynamic-execution primitive ...**\n\n- **Who:** ...\n- **Fix:** ..."
},
"locations": [{"physicalLocation": {
"artifactLocation": {"uri": "force-app/main/default/classes/VulnApex.cls"},
"region": {"startLine": 12}
}}],
"partialFingerprints": {
"vulkro/findingId": "apex-dyn-exec-soql:aa4361d464f44097",
"vulkro/v1": "...", "vulkro/v2": "...", "vulkro/locHash": "..."
},
"properties": {"vulkro.confidence": "...", "vulkro.cwe": "...", "vulkro.fix": "..."}
}]
}]
}
The markdown message carries the same explanation as the terminal: who can reach the code, the source and flow, the fix, and how to verify it.
Fingerprints
Each result carries partialFingerprints, including vulkro/findingId (the same id the terminal prints), so a code-scanning tool keeps one alert per finding across runs instead of opening new alerts when code moves.
Severity mapping
| Vulkro severity | SARIF level |
|---|---|
| Critical, High | error |
| Medium | warning |
| Low, Info | note |
Low-confidence findings below --min-confidence stay in the SARIF as suppressed results, so a dismissal is not lost. Findings hidden by a // vulkro:disable comment are dropped unless you pass --no-suppress.
Exit codes
The format does not change the exit code: 0 no findings, 1 findings (or no licence), 2 error. In CI, upload with if: always() so the SARIF arrives even when the scan step fails.
See also: GitHub Actions, Output formats