You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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).
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.
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.
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.
--ignore the affected vulnerability IDs. Does not work — uv audit's --ignore flag filters after deserialization, but the failure happens during deserialization.
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:
A uv release containing astral-sh/uv#19496 (or equivalent fix) is available — currently expected in 0.11.16 or later.
The version pin in .github/workflows/security-audit.yml (astral-sh/setup-uvversion: 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.
Summary
The
Security Auditworkflow (.github/workflows/security-audit.yml) currently fails on every run becauseuv auditcannot 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 auditstep fails with: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".
PYSEC-2026-89(and other PYSEC records, e.g. forpyjwt) includes an empty{}inaffected.ranges.events.eventsentries must contain either anintroducedorfixedvalue.uv audit's Rust deserializer is strict and rejects the malformed record, aborting the entire audit (no fallback, no skip).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
jsonandjqboth parse it without complaint).--output-format jsonhandling — 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
@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.pip-audit(PyPA's vulnerability scanner). It hits the same OSV API but parses the response more leniently. Robust, but requires exportinguv.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.--ignorethe affected vulnerability IDs. Does not work —uv audit's--ignoreflag filters after deserialization, but the failure happens during deserialization.--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:
error decoding response bodyinuv audit's stderr.::warning::annotation (linking back to this issue and toastral-sh/uv#19492), skips the auto-fix step, and exits successfully.uv auditexit 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 auditoutput periodically until the upstream fix lands.Resolution criteria
Close this issue when both of the following are true:
astral-sh/uv#19496(or equivalent fix) is available — currently expected in 0.11.16 or later..github/workflows/security-audit.yml(astral-sh/setup-uvversion:input) is bumped to that release.At that point, the
error decoding response bodyshim in the workflow should be removed so that any future audit failures (including new upstream bugs) surface immediately rather than silently passing.References