# How OSV-Scanner Handles Deprecated Packages: Detection, Filtering, and Reporting

> Learn how OSV-Scanner detects, filters, and reports deprecated packages. Discover security findings even without CVEs using its dedicated deprecation plugin.

- Repository: [Google/osv-scanner](https://github.com/google/osv-scanner)
- Tags: deep-dive
- Published: 2026-04-25

---

**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`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/scan.go) (lines 87-89), the scanner checks this flag during initialization to activate the enrichment plugin:

```go
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`](https://github.com/google/osv-scanner/blob/main/pkg/models/results.go) (line 350). Each package record carries a dedicated boolean field:

```go
Deprecated bool

```

During result construction in [`pkg/osvscanner/vulnerability_result.go`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/vulnerability_result.go) (lines 57-66), the scanner copies this flag from the inventory into the vulnerability result:

```go
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`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/filter.go) (lines 18-21):

```go
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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/internal/output/vertical.go), line 109): Prints a dedicated "Deprecated Packages Found" header section.
- **Plain table** ([`internal/output/table.go`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/internal/output/githubannotation.go)): Generates annotation tables specifically highlighting deprecated packages.

For example, the table renderer highlights deprecation status with red text formatting:

```go
if pkg.Deprecated {
    fmt.Fprintf(out, " %s ", text.FgRed.Sprintf("deprecated"))
}

```

## Summary

- OSV-Scanner requires the `--experimental-flag-deprecated-packages` flag to enable deprecated package detection via the `packagedeprecation` plugin.
- The `Deprecated` boolean field in `models.Package` tracks status throughout the scan pipeline from [`pkg/models/results.go`](https://github.com/google/osv-scanner/blob/main/pkg/models/results.go).
- Deprecated packages bypass standard filtering logic through explicit checks in [`vulnerability_result.go`](https://github.com/google/osv-scanner/blob/main/vulnerability_result.go) and [`filter.go`](https://github.com/google/osv-scanner/blob/main/filter.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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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`](https://github.com/google/osv-scanner/blob/main/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.