How OSV-Scanner Handles Deprecated Packages: Detection, Filtering, and Reporting
OSV-Scanner treats deprecated packages as first-class security findings, surfacing them in every output format—even when no CVEs exist—by using the experimental --experimental-flag-deprecated-packages flag to activate a dedicated deprecation plugin.
The google/osv-scanner repository provides built-in support for identifying deprecated packages as critical maintenance risks. When enabled, the scanner elevates package deprecation to the same significance level as known vulnerabilities, ensuring outdated dependencies are never silently ignored during CI/CD audits.
Enabling Deprecated Package Detection
Deprecated package handling in OSV-Scanner is gated behind the experimental flag --experimental-flag-deprecated-packages, represented as FlagDeprecatedPackages in the source. In pkg/osvscanner/scan.go (lines 87-89), the scanner checks this flag during initialization to activate the enrichment plugin:
if actions.FlagDeprecatedPackages {
actions.PluginsEnabled = append(actions.PluginsEnabled, packagedeprecation.Name)
}
When the flag is set, the packagedeprecation plugin is appended to the active plugin list. This plugin enriches every extracted package with a boolean Deprecated field during the scanning phase.
Storing Deprecation Status in the Data Model
The deprecation state persists in the models.Package struct defined in pkg/models/results.go (line 350). Each package record carries a dedicated boolean field:
Deprecated bool
During result construction in pkg/osvscanner/vulnerability_result.go (lines 57-66), the scanner copies this flag from the inventory into the vulnerability result:
pkg.Package.Deprecated = p.Deprecated
if pkg.Package.Deprecated {
includePackage = true // Force inclusion regardless of vulnerability count
}
This logic ensures that deprecated packages are always included in the final results, even when no CVEs are associated with them.
Filtering Logic for Deprecated Packages
OSV-Scanner typically filters out packages with no findings to reduce noise. However, deprecated packages bypass this filter through explicit protection in pkg/osvscanner/filter.go (lines 18-21):
if allPackages || len(newVulns.Vulnerabilities) > 0 ||
len(pkgVulns.LicenseViolations) > 0 ||
pkgVulns.Package.Deprecated { // Preserves deprecated packages
newPackages = append(newPackages, newVulns)
}
The condition || pkgVulns.Package.Deprecated guarantees that deprecated packages survive the filtering stage and appear in the final report.
Exit Code Behavior for Deprecated Packages
The scanner's sentinel error ErrVulnerabilitiesFound—defined in pkg/osvscanner/osvscanner.go (lines 107-110)—includes package deprecation in its definition. Consequently, when deprecated packages are detected, OSV-Scanner exits with the same non-zero code used for vulnerabilities, breaking CI pipelines unless explicitly handled.
Rendering Deprecated Packages Across Output Formats
OSV-Scanner surfaces deprecated packages in every supported output format, reading from result.PkgDeprecatedCount:
- Vertical table (
internal/output/vertical.go, line 109): Prints a dedicated "Deprecated Packages Found" header section. - Plain table (
internal/output/table.go, line 211): Renders rows with a red "deprecated" indicator for each affected package. - CycloneDX SBOM (
internal/output/sbom/cyclonedx_common.go, lines 93-100): Adds a deprecated component attribute to the generated SBOM metadata. - GitHub Annotations (
internal/output/githubannotation.go): Generates annotation tables specifically highlighting deprecated packages.
For example, the table renderer highlights deprecation status with red text formatting:
if pkg.Deprecated {
fmt.Fprintf(out, " %s ", text.FgRed.Sprintf("deprecated"))
}
Summary
- OSV-Scanner requires the
--experimental-flag-deprecated-packagesflag to enable deprecated package detection via thepackagedeprecationplugin. - The
Deprecatedboolean field inmodels.Packagetracks status throughout the scan pipeline frompkg/models/results.go. - Deprecated packages bypass standard filtering logic through explicit checks in
vulnerability_result.goandfilter.go. - The scanner uses exit code behavior identical to CVE findings when deprecated packages are present, ensuring CI/CD visibility.
- All output formats—including JSON, SARIF, CycloneDX, and human-readable tables—dedicatedly report deprecated packages using
PkgDeprecatedCount.
Frequently Asked Questions
How do I enable deprecated package detection in OSV-Scanner?
Pass the --experimental-flag-deprecated-packages command-line flag. This activates the packagedeprecation plugin, which enriches package metadata with deprecation status during the scan according to pkg/osvscanner/scan.go.
Will OSV-Scanner report deprecated packages that have no CVEs?
Yes. Deprecated packages are treated as first-class findings and are included in output even when they have zero associated vulnerabilities. The includePackage logic in pkg/osvscanner/vulnerability_result.go forces their inclusion regardless of CVE count.
How does OSV-Scanner represent deprecated packages in SBOM outputs?
When generating CycloneDX SBOMs, OSV-Scanner adds a deprecated attribute to the component metadata in internal/output/sbom/cyclonedx_common.go (lines 93-100). This allows downstream tools to identify deprecated dependencies directly from the SBOM artifact.
Does finding deprecated packages change OSV-Scanner's exit code?
Yes. Because ErrVulnerabilitiesFound in pkg/osvscanner/osvscanner.go (lines 107-110) encompasses deprecated packages, the scanner returns a non-zero exit code when deprecated packages are detected, causing CI/CD pipelines to fail unless the error is explicitly handled.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →