fix(deps): clear the two Rust advisories and make cargo audit blocking (#3121)
## Description
An independent OSV sweep of every locked package in the repo (1,463
across PyPI, crates.io and npm) surfaced three RUSTSEC advisories that
**no gate was reporting**:
| advisory | package | status |
|---|---|---|
| RUSTSEC-2026-0258 (GHSA-q83h-524g-xf6h) | h2 0.4.15 | fixed here →
0.4.16 |
| RUSTSEC-2026-0204 | crossbeam-epoch 0.9.18 | fixed here → 0.9.20 |
| RUSTSEC-2024-0436 | paste 1.0.15 | unmaintained, **no patched version
exists** |
**h2 is the one that matters.** It accepted and queued empty DATA frames
without limit; a peer that never drains a stream drives unbounded memory
growth, or a panic when the length overflows. It is not a corner of the
tree — it reaches the published wheel (`hf-hub -> headroom-core ->
headroom-py`) and the entire axum/reqwest/aws-config surface of
`headroom-proxy`.
**Why none of this was visible** is the more important half of this PR.
The `audit` job was already correct in one respect I initially misread —
the `rust-changes` job reports `rust=true` for `schedule`, so it *does*
run nightly rather than only on Rust changes. The actual defect is that
`cargo audit` was `continue-on-error: true`. It has been faithfully
reporting findings into a green run that nobody looks at.
Two of the three are also invisible to Dependabot entirely:
`crossbeam-epoch` and `paste` are RUSTSEC-only with no GHSA, so the
advisory database GitHub scans does not contain them. This job is their
only possible coverage.
## Type of Change
- [x] Bug fix (non-breaking change that fixes an issue)
## Changes Made
- `Cargo.lock`: `h2` 0.4.15 → 0.4.16, `crossbeam-epoch` 0.9.18 → 0.9.20.
Version + checksum only, 4 lines each way.
- `.github/workflows/rust.yml`: dropped `continue-on-error: true` from
the `cargo audit` step. `cargo deny check licenses` is deliberately left
soft-fail — `deny.toml` documents itself as intentionally permissive for
now, and tightening license policy is a separate decision.
- `.cargo/audit.toml` (new): lists `RUSTSEC-2024-0436` as accepted, with
the reason. Path matters — cargo-audit reads `.cargo/audit.toml`; a
root-level `audit.toml` is silently ignored.
`paste` is unmaintained rather than vulnerable, and there is nothing to
move to. It arrives via `tokenizers -> paste` and `rav1e -> paste`, both
under `fastembed`, so it is not actionable at our layer. Worth
revisiting when `tokenizers` adopts `pastey`.
## Testing
- [x] Manual testing performed
### Test Output
```text
Checksums verified against the real crates.io tarballs, not just the API field:
OK h2 0.4.16 (173331 bytes)
lock : a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27
real : a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27
OK crossbeam-epoch 0.9.20 (47545 bytes)
lock : 2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f
real : 2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f
Dependency-set equality (crates.io API, kind=normal):
h2 0.4.15 -> 0.4.16 : 11 deps before, 11 after, identical
crossbeam-epoch 0.9.18 -> .20: 2 deps before, 2 after, identical
```
## Real Behavior Proof
- Environment: macOS (darwin 25.4.0), worktree off `main` @ `b77d6129`.
**`cargo` is not installed on this machine** — see below.
- Exact command / steps: (1) parsed `uv.lock`, `Cargo.lock` and all four
`package-lock.json` files into 1,463 unique (ecosystem, name, version)
tuples and queried `api.osv.dev/v1/querybatch`, then pulled full records
for every hit; (2) walked `Cargo.lock` to find which workspace crates
actually reach `h2`, `crossbeam-epoch` and `paste`; (3) fetched both
crates' dependency lists from the crates.io API at the old and new
versions and compared them; (4) downloaded both `.crate` tarballs and
computed SHA-256 locally.
- Observed result: both bumps are patch-level with **byte-identical
dependency sets**, so the edited `Cargo.lock` is exactly what `cargo
update -p h2 -p crossbeam-epoch` would produce, and both checksums match
the real tarballs. `h2` 0.4.16 was published 2026-08-17, which is also
why Dependabot has not raised it yet.
- Not tested: I could not run `cargo audit`, `cargo build` or the test
suite locally — cargo is not installed here. **The lock edit is
hand-written, so CI is the real verification**, and it is well covered:
the `rust` workflow's `test`, `build`, `parity` and now-blocking `audit`
jobs all consume this lock and will fail on a bad checksum or an
unresolvable graph. I would not merge this on green-by-assertion; it
needs the `rust` jobs actually green.
## Runtime Rollout Safety
- Rollout-managed feature(s): None.
- Minimum rollout channel: n/a
- Stable/default behavior changed: No runtime behavior changes. CI
becomes stricter: `cargo audit` can now fail a build.
- Kill switch / disable path: re-adding `continue-on-error: true`
restores the previous (useless) behavior.
- Unsafe override required: No.
- Qualification impact: A newly-disclosed RUSTSEC advisory will now turn
the nightly Rust run red instead of being silently absorbed. That is the
intent, but it does mean advisories become someone's problem on
disclosure day — the escape hatch is a documented entry in
`.cargo/audit.toml`.
- Rollback path: Revert the commit.
## Review Readiness
- [x] I have performed a self-review
- [x] This PR is ready for human review
## Additional Notes
Deliberately **not** bundled here, each worth its own change:
- **`npm` has no audit gate at all** — no `npm audit` anywhere in
`.github/`. Current npm exposure is only `nanoid` 3.3.17
(GHSA-2v37-7h3g-55p8) in three lockfiles, all `dev: true`, which GitHub
auto-dismissed correctly. Low stakes today, but the gate is absent
rather than passing.
- **`pip-audit` only audits `--extra all`**, which excludes the
integration extras (`crewai`, `agno`, `autogen`, `langchain`, `strands`,
`bedrock`, `memory-stack`, `sandbox`). Every Python advisory currently
open against this repo lives in exactly that blind spot — GitPython via
`agno` (#3120), chromadb and json-repair via `crewai`. Dependabot
catches them because it scans the whole lock; the CI gate structurally
cannot.
- **Dependabot's `docker` ecosystem is configured for `directory: /`
only**, so the five non-root Dockerfiles get no base-image updates.
Co-authored-by: Tejas Chopra <tejas@Tejass-MacBook-Pro.local>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# cargo-audit configuration for the Rust workspace.
|
||||
#
|
||||
# Path matters: cargo-audit reads `.cargo/audit.toml`, not a root-level
|
||||
# `audit.toml`. A file at the repo root is silently ignored.
|
||||
#
|
||||
# The `audit` job in .github/workflows/rust.yml is a BLOCKING gate. It runs on
|
||||
# every PR touching Rust and nightly on the schedule (the `rust-changes` job
|
||||
# reports `rust=true` for `schedule`/`workflow_dispatch`, so a newly-disclosed
|
||||
# advisory surfaces without anyone touching Rust code).
|
||||
#
|
||||
# It was `continue-on-error: true` until the change that added this file, which meant it reported findings
|
||||
# nobody saw: RUSTSEC-2026-0258 (h2, unbounded empty DATA frames) sat in a green
|
||||
# run. Anything ignored here has to be listed explicitly, with a reason.
|
||||
|
||||
[advisories]
|
||||
ignore = [
|
||||
# `paste` is unmaintained — an advisory of project status, not a
|
||||
# vulnerability; there is no patched version to move to. It is transitive
|
||||
# and unavoidable at our layer: tokenizers -> paste and rav1e -> paste,
|
||||
# both reached via fastembed. Re-evaluate when tokenizers moves to
|
||||
# `pastey` (the maintained drop-in fork).
|
||||
"RUSTSEC-2024-0436",
|
||||
]
|
||||
@@ -224,8 +224,12 @@ jobs:
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-audit,cargo-deny
|
||||
- name: cargo audit (soft-fail)
|
||||
continue-on-error: true
|
||||
# Blocking. Soft-failing this made it useless: RUSTSEC-2026-0258 (h2,
|
||||
# unbounded empty DATA frames -> unbounded memory or a panic) was
|
||||
# reported by this job for as long as it existed and never turned a run
|
||||
# red, so nobody acted on it. Accepted advisories go in audit.toml with
|
||||
# a written reason rather than being swallowed wholesale here.
|
||||
- name: cargo audit
|
||||
run: cargo audit
|
||||
- name: cargo deny check licenses
|
||||
continue-on-error: true
|
||||
|
||||
Generated
+4
-4
@@ -1209,9 +1209,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
version = "0.9.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
@@ -1805,9 +1805,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.15"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
|
||||
checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
|
||||
Reference in New Issue
Block a user