SARIF output emits one result per matched advisory in an alias group, creating duplicate code scanning alerts

Open Beginner friendly
#3,093 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
github, go
Domain
cli, security

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 partialFingerprints to 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 BuildResults formatters (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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from google/osv-scanner

All issues in google/osv-scanner

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.