Skip to content

fix: don't suppress binaries owned by unrelated OS packages - #5215

Open
yzxcj797 wants to merge 1 commit into
anchore:mainfrom
yzxcj797:fix/unrelated-os-owner-binary-suppression
Open

fix: don't suppress binaries owned by unrelated OS packages#5215
yzxcj797 wants to merge 1 commit into
anchore:mainfrom
yzxcj797:fix/unrelated-os-owner-binary-suppression

Conversation

@yzxcj797

Copy link
Copy Markdown

What?

exclude-binary-overlap-by-ownership: true (the default) suppresses a binary finding when any OS package owns the file — even when the owning package is completely unrelated to the binary and carries none of its metadata. In grype this silently drops critical CVEs: a vendor RPM bundling its own OpenSSL 3.5.0 owns /opt/VendorProduct/bin/openssl, the unrelated vendor-product RPM suppresses the binary finding, and CVE-2025-15467 goes unreported with no warning anywhere (anchore/grype#3670).

Fixes the syft side of anchore/grype#3670

Why?

identifyOverlappingOSRelationship excluded the child binary package purely on parent.Type ∈ OS types — no relation between the names of the owning package and the detected binary was ever considered. The exclusion exists to deduplicate a binary against the distro package that legitimately ships it (#931); applied to an unrelated owner it doesn't deduplicate anything, it just hides the only package record that knew the vendored library's identity and version.

How?

Gate the OS→binary exclusion on the owning package plausibly shipping the binary: osPackageShipsBinary(pkgName, binaryName) — exact match always qualifies; otherwise the binary name (case-insensitive) must appear in the package name, which covers the common shapes (libopenssl3, openssl-3.2.3-150700.1.1, golang-go); binary names shorter than 3 characters only match exactly, so incidental substrings can't suppress anything.

  • related owner (the original Package duplicated by different cataloger #931 dedupe intent): unchanged — the binary is still excluded;
  • unrelated owner: the binary finding is kept, so grype can match its CVEs;
  • JVM and Bitnami overlap paths: untouched.

Testing

The existing fixtures used unrelated placeholder names (package-a owning package-c), which under the gate correctly no longer exclude — they now use realistic related names (libopenssl3openssl). New cases:

Differential: on main the unrelated-owner case fails — the binary is excluded, exactly the reported silent suppression. With this change the whole internal/relationship suite passes (go test ./internal/relationship/, full package, 1.6s).

identifyOverlappingOSRelationship removed any binary package whose
file overlapped an OS package's ownership, with no check that the
owning package actually relates to the binary. A vendor RPM that
bundles its own copy of a library (owning the binary's file but
carrying none of the library's metadata) therefore suppressed the
binary finding entirely, and the library's vulnerabilities went
unreported — a critical CVE silently missed by grype
(anchore/grype#3670).

Only suppress when the owning OS package plausibly ships the binary:
package names commonly embed the upstream name with prefixes and
suffixes (libopenssl3, openssl-3.2.3-150700.1.1, golang-go), so an
exact name match is not required, but very short binary names only
match exactly to avoid suppressing on incidental substrings. The
related-owner case (the original dedupe intent from anchore#931) is
unchanged, as are the JVM and Bitnami overlap paths.

The existing test fixtures used unrelated placeholder names, which
under the new gate would (correctly) no longer be excluded, so they
now use realistic related names, and new cases cover the unrelated
owner and the short-name rule. Differential: on the previous code the
'unrelated OS owner does not exclude the binary' case fails — the
exact suppression from the report. Full internal/relationship suite
passes.
@CAOShurong

Copy link
Copy Markdown
Contributor

Independently verified this fix against the #5214 scenario on Windows (go1.26.6, exact head 9d8ac73b):

  • Full ./internal/relationship/ test suite: PASS (including the new unrelated-owner cases)
  • Wrote an additional independent test reproducing the issue's shape — an unrelated vendor-product RPM owning a file where an openssl binary was detected:
    • unrelated owner + ELF binary → not excluded (the core #5214 case) ✅
    • matching OS package name (openssl RPM → openssl binary) → still excluded ✅
    • libopenssl3openssl prefix/suffix matching still works ✅
    • short-name binaries are not suppressed by incidental substring matches ✅
  • go vet clean

One thing I noticed while reading the diff: the guard only applies when child.Type is in binaryCatalogerTypes, but the metadata branch right below (binaryMetadataTypes like ELFBinaryPackageNoteJSONPayload) can also return child.ID(). In practice those children appear to always have Type: BinaryPkg too, so the path may be unreachable via the metadata branch alone — but worth confirming the intent is to leave that second return unguarded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants