Skip to content

python: add opt-in preserve_local_version scanner config flag #1947

Description

@peteditmars

Problem

PEP 440 local version identifiers (the +local suffix, e.g. 1.2.3+rhai.22) are discarded by claircore's Python package scanner. The pep440.Version struct has no Local field, and the godoc comment states explicitly: "Local revisions are discarded." v.String() reconstructs from Epoch, Release, Pre, Post, Dev only — the local segment is permanently gone from the package record after indexing.

This causes false positive CVE reports for downstream-patching workflows: when a packager (e.g. Red Hat +rhai* builds) backports a CVE fix into a local version increment, Clair reports the package as still vulnerable. It compares the stripped version (1.2.3) against the CVE database, which still lists 1.2.3 as affected. The local version that signals the fix is present is invisible to Clair and to readers of the clair scan report.

Proposed Change

Add an opt-in flag to the Python ScannerConfig:

type ScannerConfig struct {
    ReportLocalVersion bool `json:"report_local_version" yaml:"report_local_version"`
}

When true, emit hdr.Get("Version") directly instead of v.String(). Default false — behavior is unchanged for all existing users. Public PyPI does not permit local versions, so no standard-index user would ever see a local version in Clair output; this only affects private registries and downstream patching workflows. (hdr in the above is the raw Version header from the package metadata)

This change affects scan output format only. Vulnerability matching uses NormalizedVersion (a separate field) and is not affected.

  # Current output
  "Version": "1.2.3"

  # With ReportLocalVersion: true
  "Version": "1.2.3+rhai.22"

Impact

  • No behavior change for default users (opt-in, default off)
  • Downstream consumers of Clair scan output (e.g. policy evaluation engines like Enterprise Contract) can distinguish patched builds (1.2.3+rhai.22) from unpatched ones (1.2.3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions