SARIF output emits one result per matched advisory in an alias group, creating duplicate code scanning alerts
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 88/100
Research direction
Start with internal/output/result.go at mapIDsToGroupedSARIFFinding and internal/output/sarif.go at PrintSARIFReport and run.AddRule. Reproduce the issue with the provided go.mod and osv-scanner scan command, then verify that SARIF emits one result per alias group while preserving one rule per group and the existing table behavior.
Written by the indexing model from the issue text.
Description
Hey,
We recently added the OSV Scanner GitHub Action to Distr, but it reports a lot duplicates (https://github.com/distr-sh/distr/security/code-scanning).
Happy to draft a pr in order to fix the issue.
Summary
--format=sarif emits one result per matched advisory ID within an alias group instead of one result per group. Each of those results carries the group's DisplayID as ruleId, the same location, the same message and the same partialFingerprints, so a consumer cannot tell them apart. GitHub code scanning opens one alert per result, so a package matched by both a GHSA and a GO entry for the same CVE produces two identical alerts that have to be dismissed individually.
The table output is unaffected, because it prints one row per alias group. That makes the duplication invisible in the workflow log and visible only in the Security tab.
Version
osv-scanner 2.6.0, run through ghcr.io/google/osv-scanner-action:v2.6.0. Also reproducible with the standalone CLI.
Reproduction
go.mod:
module example.com/repro
go 1.24
require github.com/docker/docker v28.5.2+incompatible
osv-scanner scan source --format=sarif --output=results.sarif -L go.mod
jq -r '.runs[0].results | group_by(.ruleId)[] | "\(.[0].ruleId) x\(length)"' results.sarif
Output, with advisory data as of 2026-09-16:
CVE-2026-33997 x2
CVE-2026-34040 x1
CVE-2026-41567 x2
CVE-2026-41568 x2
CVE-2026-42306 x2
That is 5 rules and 9 results. CVE-2026-41567 is matched through two entries that alias each other, GHSA-x86f-5xw2-fm2r and GO-2026-5746, and is emitted twice. CVE-2026-34040 is matched through GO-2026-4887 only and is emitted once. The two results for a doubled rule are identical in ruleId, locations, message.text and partialFingerprints.primaryLocationLineHash.
Root cause
mapIDsToGroupedSARIFFinding registers one map key per matched advisory ID, all pointing at the same group object:
https://github.com/google/osv-scanner/blob/v2.6.0/internal/output/result.go#L229-L231
PrintSARIFReport then iterates over every key of that map and appends a result per iteration:
https://github.com/google/osv-scanner/blob/v2.6.0/internal/output/sarif.go#L259-L267
run.AddRule(gv.DisplayID) deduplicates by rule ID, which is why the rule count stays at one per group while the result count grows:
https://github.com/google/osv-scanner/blob/v2.6.0/internal/output/sarif.go#L301
The CVE never becomes a key itself, since gi.IDs holds only the IDs of matched entries, so the number of duplicates equals the number of matched advisories in the group rather than the length of the alias list.
Expected behaviour
One SARIF result per alias group, per package and source, matching what the table output reports.
Suggested fix
Skip a group that has already been emitted in that loop, for example with a seen map[*groupedSARIFFinding]bool, which preserves the deterministic ordering that the sorted key iteration provides.
Related
- #2331 added
partialFingerprintsto fix duplicates in GitHub's output. It cannot help here, because these duplicate results are byte-identical, including the fingerprint. - #3086 covers duplicate packages in the
BuildResultsformatters (table, vertical, Markdown, HTML) caused by ecosystem prefix collisions. SARIF does not use that code path.
Best, Philip
- Dominant language
- Go
- Stars
- 11.1k
- Forks
- 794
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 48
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from google/osv-scanner
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
google/osv-scanner#2981 · 4 comments ·
-
getNextFixVersion panics on an advisory with an unparsable `fixed` version, crashing result output Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
google/osv-scanner#2936 · 4 comments ·
-
backlog
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
google/osv-scanner#1840 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
google/osv-scanner#3073 · 3 comments ·
-
google/osv-scanner#3057 · 4 comments · 1 assignee ·
All issues in google/osv-scanner
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
-
enhancement needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
kind/cleanup
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
kubernetes-sigs/kueue#15947 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
sympozium-ai/sympozium#627 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100