feat(audit): add SARIF 2.1.0 output for the report mode (#488)#955
Open
ChrisJr404 wants to merge 1 commit into
Open
feat(audit): add SARIF 2.1.0 output for the report mode (#488)#955ChrisJr404 wants to merge 1 commit into
ChrisJr404 wants to merge 1 commit into
Conversation
GitHub code scanning, GitLab Vulnerabilities, Sonar, Azure DevOps and
several other consumers ingest SARIF 2.1.0 to display security findings
in their UIs. Today detect-secrets users have to write a glue script to
convert 'detect-secrets audit --report' JSON into SARIF before feeding
it to those systems. This adds a native '--sarif' switch.
Activation:
detect-secrets audit --report --sarif <baseline> > findings.sarif
The conversion is a thin layer over audit.report.generate_report so the
SARIF view is always consistent with the existing JSON report (filter
flags --only-real / --only-false work the same way).
Mapping
Result.ruleId the detect-secrets plugin name (Type)
Result.message.text '<plugin> detected: <verified-result>'
Result.kind 'open' for true positives, 'review' for
false-positives. SARIF spec section 3.27.9.
Result.level 'error'
Result.locations[0] physicalLocation w/ artifactLocation.uri,
region.startLine, region.snippet.text
Result.partialFingerprints
'detectSecretsHash/v1' = file:plugin:line so
consumers can dedupe across runs without ever
seeing the secret value
Result.properties.category
original detect-secrets VerifiedResult name
Tool driver advertises the detect-secrets package version (read at
runtime from __version__) plus an informationUri pointing back at the
GitHub repo.
Tests
tests/audit/sarif_test.py
test_envelope_structure required SARIF fields
test_results_contain_findings location + fingerprint shape
test_only_real_filter --only-real
test_only_false_filter --only-false
test_kind_field_reflects_classification open vs review
Live-verified end-to-end: scanned a fixture file containing an AWS
access key and a GitHub PAT, generated a baseline, ran 'audit --report
--sarif', and the output validates against the SARIF 2.1.0 schema URL
embedded in the document.
Full audit + main test suites: 53/53 passed (tests/audit/ +
tests/main_test.py). Failures in tests/filters/{gibberish,wordlist}_test
and tests/plugins/base_test::test_handle_verify_exception_gracefully
pre-date this change and are unrelated to audit/.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #488.
GitHub code scanning, GitLab Vulnerabilities, Sonar, Azure DevOps and several other consumers ingest SARIF 2.1.0 to display security findings in their UIs. Today detect-secrets users have to write a glue script to convert `detect-secrets audit --report` JSON into SARIF before feeding it to those systems — this adds a native `--sarif` switch.
@lorenzodb1 mentioned in #488 that the team had a hard time finding an easy conversion path; the implementation here doesn't pull in any new dependencies (no `microsoft/sarif-python-om`, no jsonschema runtime), it just emits the SARIF 2.1.0 dict directly, validated against the schema URL embedded in the document.
Usage
```bash
detect-secrets audit --report --sarif .secrets.baseline > findings.sarif
```
`--only-real` / `--only-false` work the same way as on the existing JSON report.
Mapping
Implementation
Tests
`tests/audit/sarif_test.py`:
Test results
`tests/audit/` + `tests/main_test.py`: 53 passed.
```
tests/audit/sarif_test.py::test_envelope_structure PASSED
tests/audit/sarif_test.py::test_results_contain_findings PASSED
tests/audit/sarif_test.py::test_only_real_filter PASSED
tests/audit/sarif_test.py::test_only_false_filter PASSED
tests/audit/sarif_test.py::test_kind_field_reflects_classification PASSED
```
Failures elsewhere in the suite (`tests/filters/{gibberish,wordlist}`, `tests/plugins/base_test::test_handle_verify_exception_gracefully`, `tests/pre_commit_hook_test::test_quit_if_baseline_is_changed_but_not_staged`) pre-date this PR and are unrelated to the audit module.
Live-verify
Scanned a fixture file with an AWS access key + GitHub PAT and generated a baseline:
```json
{
"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json\",
"version": "2.1.0",
"runs": [
{
"tool": {"driver": {"name": "detect-secrets", "version": "1.5.0", ...}},
"results": [
{
"kind": "open",
"level": "error",
"locations": [{"physicalLocation": {
"artifactLocation": {"uri": "config.py"},
"region": {"startLine": 1, "snippet": {"text": "AWS_ACCESS_KEY_ID = ..."}}
}}],
"message": {"text": "Potential secret detected by AWS Access Key: unverified."},
"partialFingerprints": {"detectSecretsHash/v1": "config.py:AWS Access Key:1"},
"properties": {"category": "UNVERIFIED"},
"ruleId": "AWS Access Key",
"ruleIndex": 0
},
...
]
}
]
}
```