Skip to content

[Bug] OSV batch results are paired to query packages by array position, not identity #987

Description

@sonukapoor

Note: this is an in-house item already being handled by the maintainer - not open for contribution. Filed for tracking only.

Summary

The scan pipeline pairs OSV querybatch results to the queried packages purely by array position, in two places, and ignores the package identity it already carries. If OSV ever returns a results array that is out of order or shorter than the query list, vulnerabilities are attributed to the wrong package, or packages are silently recorded as clean.

OSV's API contract guarantees one result per query in query order, so this does not fire in normal operation. But it is an unguarded positional assumption in security-critical code, and the identity needed to make it robust is already available.

Where

  • src/advisory/osv-advisory-source.ts (queryBatch): builds rows as data.results.map((r, i) => ({ package: packages[i].name, version: packages[i].version, vulnerabilities: r.vulns || [] })) - pairs results[i] with packages[i] by index.
  • src/scanner.ts (~184-190): reads const row = rows[j] and attributes row.vulnerabilities to chunkItems[j], ignoring the row.package / row.version that queryBatch attached.

Failure modes

  1. Out-of-order results -> package A is reported with package B's vulnerabilities (misattribution).
  2. Truncated results (fewer entries than queries) -> the tail packages get rows[j] === undefined, so they are recorded as having no vulnerabilities and cached as clean (a silent false-negative). Related to [Bug] TypeError crash when OSV API returns 200 OK with missing results field #984/Fix crash when OSV API returns error in 200 response #985.

Suggested direction

Match results to packages by identity rather than position: either have scanner.ts key off the package/version that queryBatch already attaches, or assert results.length === packages.length and verify per-entry identity in queryBatch. When the response does not line up, surface a descriptive failure or a scan-completeness diagnostic (tie into #907) rather than silently mis-pairing.

Context

Found while reviewing #985. Latent (depends on OSV violating its own contract), so low urgency, but cheap to harden given the identity is already in hand.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingin-houseMaintainer-handled internal work - not open for contribution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions