Skip to content

fix(ci): tolerate upstream uv audit OSV parse failure#1423

Merged
sscargal merged 1 commit into
MemMachine:mainfrom
sscargal:fix/security-audit-workflow-osv-shim
May 20, 2026
Merged

fix(ci): tolerate upstream uv audit OSV parse failure#1423
sscargal merged 1 commit into
MemMachine:mainfrom
sscargal:fix/security-audit-workflow-osv-shim

Conversation

@sscargal

Copy link
Copy Markdown
Contributor

Summary

Stops the Security Audit workflow from blocking unrelated PRs while we wait for the upstream uv/OSV bug fix. When (and only when) uv audit exits non-zero with the specific error decoding response body failure, the workflow now:

  • Forwards uv's stderr to the run log for visibility.
  • Emits a GitHub Actions ::warning:: annotation plus a Step Summary explaining what was skipped, why, and how to remove the shim.
  • Sets has_vulnerabilities=false so the downstream upgrade and PR-creation steps no-op cleanly.
  • Exits successfully.

All other uv audit exit codes >1 still fail loudly.

Root cause (not in this repo)

Upstream: astral-sh/uv#19492. An OSV record (PYSEC-2026-89 and similar) contains an empty {} in affected.ranges.events — invalid per OSV's schema. uv's strict Rust deserializer rejects the record, aborting the entire audit before any vulnerabilities can be reported. uv maintainers (@woodruffw) are deliberately holding back the lenient-parser fix (astral-sh/uv#19496) so OSV fixes the bad records upstream first.

Locally reproducible against this repo's uv.lock: 5/5 attempts fail with the same error, so this is not transient.

Why a shim (and not pip-audit / waiting)

Considered alternatives:

  • Switch to pip-audit — robust, but requires re-implementing the JSON parse + upgrade loop around its different schema. Held in reserve if upstream takes weeks.
  • Wait — leaves CI red on every PR until upstream merges.
  • uv audit --ignore <id> — does not help; uv's --ignore filters after deserialization, and the parse aborts before filtering.
  • Mirror OSV via --service-url — no maintained mirror exists.

The shim is the smallest reversible change that keeps PRs unblocked. It is gated on a very specific error string so it does not silently swallow other failure modes.

Verification

Dispatched on this branch via workflow_dispatch:

  • Job conclusion: success.
  • Step Run security audit: emits ##[warning]uv audit could not decode the OSV response (known upstream bug astral-sh/uv#19492)….
  • Steps Upgrade vulnerable packages and Create security fix pull request: both skipped (correct, because has_vulnerabilities=false).
  • Step Summary contains a markdown block explaining the skip, with links to both the upstream issue and the resolution criteria.

Run: https://github.com/sscargal/MemMachine/actions/runs/26188026375

How to remove this shim (resolution criteria)

When both of the following are true, delete the grep -qF 'error decoding response body' branch in .github/workflows/security-audit.yml:

  1. A uv release containing astral-sh/uv#19496 (or an equivalent fix) is available.
  2. The astral-sh/setup-uv version: input is bumped to that release.

The in-repo tracking issue (to be filed alongside this PR) lists the full analysis, root cause, ruled-out theories, possible workarounds, and the decision to wait for upstream.

Test plan

  • Dispatched the workflow on this branch with the current uv.lock (which triggers the OSV parse failure) — exits success with the warning annotation
  • Verified downstream steps (Upgrade vulnerable packages, Create security fix pull request) are skipped cleanly when has_vulnerabilities=false
  • On merge, confirm the next Dependabot / scheduled-cron run also exits success with the same warning
  • Once the upstream fix ships, remove the shim and bump the setup-uv version: input

Signed-off-by: Steve Scargall 37674041+sscargal@users.noreply.github.com

Temporarily skip the workflow when `uv audit` exits non-zero due to the
upstream OSV/uv deserialization bug (astral-sh/uv#19492). The bad OSV
record (PYSEC-2026-89 and similar) contains an empty `{}` in
`affected.ranges.events`, which uv's strict Rust deserializer rejects,
aborting the entire audit before vulnerabilities can be reported.

The workflow now:

- Captures uv audit's stderr separately and forwards it to the run log.
- Detects the specific `error decoding response body` failure mode.
- Emits a GitHub Actions ::warning:: annotation plus a Step Summary
  explaining what was skipped, why, and how to remove the shim.
- Exits successfully so unrelated PRs aren't blocked while we wait for
  the upstream fix (astral-sh/uv#19496 or equivalent).

All other uv audit error exit codes (>1) still fail loudly. Once the
`setup-uv` version is bumped past 0.11.15 to a release containing the
upstream fix, the workaround branch should be removed so future audit
regressions surface immediately.

Signed-off-by: Steve Scargall <37674041+sscargal@users.noreply.github.com>
@sscargal sscargal merged commit 90e8475 into MemMachine:main May 20, 2026
31 of 44 checks passed
@sscargal sscargal deleted the fix/security-audit-workflow-osv-shim branch May 20, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant