Python Analyzer (Scanner)

What it does

Inputs and precedence

  1. Installed inventory (preferred): detect site-packages roots and parse *.dist-info/ / *.egg-info/ metadata for concrete pkg:pypi/<name>@<version> components.
  2. Archive inventory: mount wheels (*.whl) and zipapps (*.pyz, *.pyzw) into the Python VFS and enrich any in-archive *.dist-info/ metadata (including RECORD verification).
  3. Lock augmentation (current): parse root-level requirements*.txt pinned entries (==/===), Pipfile.lock default section, and poetry.lock; when a lock entry matches an installed component, merge lock metadata.
  4. Declared-only (current): lock entries not present in installed inventory still emit components:
    • concrete versions emit a versioned pkg:pypi/...@<version> PURL
    • non-concrete declarations (e.g., editable paths) emit explicit-key components (see Identity Rules)

Project discovery (including container roots)

The analyzer is layout-aware and bounded:

Virtual filesystem (VFS) and determinism

Identity rules (PURL vs explicit key)

Concrete versions emit a PURL:

Non-concrete declarations emit an explicit key:

Editable declarations (from requirements --editable / -e) normalize the specifier:

Evidence and metadata

Installed and archive distributions emit evidence for (when present):

RECORD verification emits deterministic counters:

Declared-only/lock-only components include:

Container overlay semantics (pending contract)

When scanning raw OCI layer trees, correct overlay/whiteout handling is contract-driven. Until that contract lands, treat per-layer inventory as best-effort and do not rely on it as a merged-rootfs truth source.

Vendored/bundled packages (pending contract)

Vendored directory signals are detected but representation (separate components vs parent-only metadata) is contract-driven to avoid false vulnerability joins.

References