Skip to content

Security Audit workflow blocked by upstream uv audit OSV parse failure (#19492) #1424

@sscargal

Description

@sscargal

Summary

The Security Audit workflow (.github/workflows/security-audit.yml) currently fails on every run because uv audit cannot parse the response it gets from the OSV vulnerability database. This is an upstream bug, not a defect in our workflow.

Symptoms

The Run security audit step fails with:

error: error decoding response body
  Caused by: expected value at line 1 column <N>
uv audit exited with unexpected status: 2
Error: Process completed with exit code 2.

The column number varies between runs (observed: 791, 1012, 1206) because the response body length depends on which packages are in the lockfile and what advisories OSV currently has on file.

Root cause

Tracked upstream as astral-sh/uv#19492"uv audit fails with error decoding response body when OSV returns empty range events".

  • OSV record PYSEC-2026-89 (and other PYSEC records, e.g. for pyjwt) includes an empty {} in affected.ranges.events.
  • That field violates the OSV schema: events entries must contain either an introduced or fixed value.
  • uv audit's Rust deserializer is strict and rejects the malformed record, aborting the entire audit (no fallback, no skip).
  • See upstream confirmation: PYSEC-2025-18 invalid range? pypa/advisory-database#284 (same problem hit pyjwt).

The bug is fully reproducible locally against this repo's uv.lock (5/5 attempts fail with the same error), and it is not transient.

What was ruled out

  • Not a transient network/API error — verified by hammering the OSV endpoint manually; the response itself is well-formed JSON (Python's json and jq both parse it without complaint).
  • Not a uv version regression — confirmed in the upstream issue that downgrading to 0.11.14 does not help; the parser is identical.
  • Not our --output-format json handling — the workflow correctly surfaces the underlying uv error (uv audit exited with unexpected status: 2) after fix(ci): resolve security-audit workflow failures #1421.

Possible workarounds

  1. Wait for the upstream fix (chosen). uv PR #19496 makes uv resilient to malformed OSV records, but maintainers (@woodruffw) are deliberately holding it back so that OSV upstream fixes the bad records first. We will pull this in via the normal uv version bump once it ships.
  2. Switch to pip-audit (PyPA's vulnerability scanner). It hits the same OSV API but parses the response more leniently. Robust, but requires exporting uv.lock -> requirements.txt, adopting a different JSON schema, and re-implementing the upgrade loop around its output. Held in reserve in case the upstream fix is delayed for weeks.
  3. --ignore the affected vulnerability IDs. Does not work — uv audit's --ignore flag filters after deserialization, but the failure happens during deserialization.
  4. Pin to an older OSV mirror via --service-url. No widely-maintained mirror exists; the bad records would propagate anyway.

Interim mitigation (this issue)

To stop the workflow from blocking unrelated PRs while we wait for upstream:

  • The workflow detects the specific error string error decoding response body in uv audit's stderr.
  • When that error is the cause of a non-zero exit, the workflow emits a ::warning:: annotation (linking back to this issue and to astral-sh/uv#19492), skips the auto-fix step, and exits successfully.
  • All other uv audit exit codes greater than 1 continue to fail the workflow loudly.

This is a deliberate, time-limited compromise: PRs are not blocked, but for the duration of the workaround we are not actively scanning for new CVEs. Maintainers should manually check uv audit output periodically until the upstream fix lands.

Resolution criteria

Close this issue when both of the following are true:

  1. A uv release containing astral-sh/uv#19496 (or equivalent fix) is available — currently expected in 0.11.16 or later.
  2. The version pin in .github/workflows/security-audit.yml (astral-sh/setup-uv version: input) is bumped to that release.

At that point, the error decoding response body shim in the workflow should be removed so that any future audit failures (including new upstream bugs) surface immediately rather than silently passing.

References

Metadata

Metadata

Assignees

Labels

choreRoutine maintenance tasks that don't directly affect the codebase's functionality.securitySecurity-related tasks that come from private reports, code scanning, and vulnerability checks.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions