Skip to content

fix(deps): crossbeam-epoch 0.9.20 for RUSTSEC-2026-0204 - #13

Open
noahgift wants to merge 3 commits into
mainfrom
fix/rustsec-2026-0204-crossbeam-epoch
Open

fix(deps): crossbeam-epoch 0.9.20 for RUSTSEC-2026-0204#13
noahgift wants to merge 3 commits into
mainfrom
fix/rustsec-2026-0204-crossbeam-epoch

Conversation

@noahgift

@noahgift noahgift commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

RUSTSEC-2026-0204

crossbeam-epoch 0.9.18 → 0.9.20. Invalid pointer dereference in the fmt::Pointer impl for Atomic/Shared. Patch-level lockfile bump. Found via the fleet lane-liveness sweep; 90 of 94 local repos carried the vulnerable version. PMAT-203.

Second commit: three pre-existing clippy errors

The lockfile push could not land because the pre-push gate was already red on clippy. All three are new-in-1.95 lints that appeared with a toolchain bump — pre-existing, unrelated to the dependency change:

  • adapters/wos.rsSignal::Cont arm collapsed into a match guard (collapsible_if)
  • metrics.rsduration_avg had a count > 0 guard around a division; now checked_div (manual_checked_ops), which is also clearer about the divide-by-zero case
  • manager.rs — five second-valued Durations trip duration_suboptimal_units, which wants Duration::from_mins. Not taken: that constructor stabilized in Rust 1.87 and this crate declares rust-version = "1.83", so following the suggestion would silently raise the MSRV. Allowed at module scope with the reason recorded inline; revisit if the declared MSRV moves past 1.87.

Verification

cargo clippy --all-targets -- -D warnings clean, fmt clean, pre-push gate passes, and cargo audit no longer reports 0204.

🤖 Generated with Claude Code

noahgift and others added 3 commits July 30, 2026 08:48
RUSTSEC-2026-0204: invalid pointer dereference in the `fmt::Pointer` impl for
`Atomic` and `Shared` when the underlying pointer is invalid. Fixed upstream in
0.9.20; this is a patch-level lockfile bump inside the existing semver range, so
only Cargo.lock changes.

Found by running the fleet lane-liveness dead-man's switch: whisper.apr, pepita
and pzsh Nightly Bench had all been failing for exactly 23 days on this one
advisory, matching its publication date. A scan then found 90 of 94 local repos
carrying the vulnerable 0.9.18.

Verified: `cargo audit` no longer reports RUSTSEC-2026-0204 for this repo. Other
pre-existing advisories, where present, are untouched.

Refs PMAT-203
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ush gate

Found while landing the RUSTSEC-2026-0204 lockfile bump (previous commit): the
local pre-push gate was already red on clippy, so that push could not land. All
three are pre-existing and unrelated to the dependency change — they are new-in-
1.95 lints that appeared with a toolchain bump, not new code.

  * adapters/wos.rs: `Signal::Cont` arm collapsed into a match guard
    (collapsible_if).
  * metrics.rs: `duration_avg` used a `count > 0` guard around a division;
    now `checked_div` (manual_checked_ops), which is also clearer about the
    divide-by-zero case.
  * manager.rs: five second-valued Durations trip `duration_suboptimal_units`,
    which wants `Duration::from_mins`. NOT taken — that constructor stabilized in
    Rust 1.87 and this crate declares `rust-version = "1.83"`, so following the
    suggestion would silently raise the MSRV. Allowed at module scope with that
    reason recorded inline; revisit if the declared MSRV moves past 1.87.

Verified: `cargo clippy --all-targets -- -D warnings` clean, fmt clean, and the
pre-push gate passes.

Refs PMAT-203
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e catches

I verified the previous commit with `cargo clippy --all-targets`, but CI runs
`cargo clippy --workspace -- -D warnings`. Different scope: --workspace reaches
duende-test, which has five more `duration_suboptimal_units` sites in chaos.rs
and load.rs. My local command could not have caught it — the same
verify-the-effective-artifact mistake, one layer up.

Allowed at crate scope with the same rationale as duende-core's manager.rs:
`Duration::from_mins` stabilized in Rust 1.87 and this workspace declares
rust-version 1.83, so taking clippy's suggestion would silently raise the MSRV.

Verified with CI's exact commands: `cargo fmt --all -- --check` and
`cargo clippy --workspace -- -D warnings` both clean.

Noted, not fixed: `--workspace --all-targets` reports 59 pre-existing findings
across test and bench targets. CI does not gate that surface and it is unrelated
to this dependency bump.

Refs PMAT-203
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Aug 28, 2026
The `gate` job added in the previous commit did what it was built to do
on its first run: it went red, because two of the four CI jobs it
aggregates are genuinely failing.

Neither failure is caused by this branch — it touched only ci.yml. Main's
last CI run was 2026-04-06 (green, e67a0d4) and nothing has run on main
since. Both jobs pin rolling inputs, so both rotted unobserved for five
months:

  Lint     `dtolnay/rust-toolchain@stable` is now clippy 1.98
  Security `cargo audit` fetches the advisory DB at run time

Lint — two new-in-1.98 lints, both behaviour-preserving rewrites:

  adapters/wos.rs:312  collapsible_match   → `Signal::Cont if …` guard.
                       Non-Stopped Cont still falls through to `_ => {}`.
  metrics.rs:156       manual_checked_ops  → `checked_div(count)` +
                       `map_or(Duration::ZERO, …)`. count == 0 still
                       yields ZERO; the extra relaxed load is side-effect
                       free.

Security — 2 vulnerabilities, both semver-compatible patch bumps:

  crossbeam-epoch 0.9.18 → 0.9.20  RUSTSEC-2026-0204
  h2              0.4.13 → 0.4.19  RUSTSEC-2026-0258

The crossbeam-epoch bump is the same one PR #13 carries; #13 is the PR
that has been sitting BLOCKED against a green board this whole time.
Only those two packages were relocked. The 8 remaining advisories are
already-allowed `unmaintained`/`unsound` warnings, untouched.

Also refactors `WosAdapter::status`, which the pmat pre-commit hook
rejected at Cognitive 45 > 25. Measured before touching it: the
violation is entirely pre-existing and in a function this branch had no
reason to edit — the hook only scans STAGED files, so `status` had never
been weighed. The one-line lint fix above is what put wos.rs in the
staged set. That fix on its own moved the file 126 → 125 cognitive.

The 45 was nesting, not logic, so `status` splits into three helpers
with the branch structure preserved exactly:

  query_wos_ctl_status()    Ok(None) = "no answer, fall back to local
                            state"; a non-zero wos-ctl exit is an
                            ANSWER (Stopped), and that distinction is
                            the one thing easy to lose here.
  parse_wos_ctl_status()    pure str → Option<DaemonStatus>
  status_from_process_state()  pure ProcessState → DaemonStatus

wos.rs now reports no complexity violation at all. The two pure helpers
are directly unit-testable, which the nested chain was not.

Verified locally: `cargo fmt --all -- --check` clean, `cargo clippy
--workspace -- -D warnings` clean, `cargo test --workspace` 932 passed /
0 failed — the same 932 as before the refactor.

Deliberately NOT fixed: `manager.rs:94` trips
`clippy::duration_suboptimal_units` on local clippy 1.97 but NOT on CI's
1.98, which reported exactly two errors. Chasing it would fix a lint the
gate never asked for. That the two toolchains disagree in both
directions is the real hazard of `@stable` + `-D warnings`, and is worth
a follow-up pin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Aug 28, 2026
* ci: emit the `gate` status context the org ruleset requires

The paiml org ruleset "Green Main" (id 13878864) requires exactly one
status context:

    $ gh api orgs/paiml/rulesets/13878864 \
        --jq '.rules[]|select(.type=="required_status_checks")
              |.parameters.required_status_checks[].context'
    gate

No workflow in this repo emits a check named `gate`. Measured on PR #13:
all four checks are green — Test, Lint, Coverage, Security (workflow CI)
— and the PR still reports `mergeStateStatus: BLOCKED`. Nothing a
contributor can do fixes it, because the missing check is one the repo
cannot produce. The only way through is an admin override, which the org
rules forbid, correctly. Eight repos are in this state.

A required context that no workflow emits does not raise the bar, it
closes the repo.

Fix: an aggregating `gate` job in ci.yml. Job id and `name:` are both
literally `gate` because the ruleset matches the CONTEXT, not a display
name — a friendlier name silently re-breaks merging.

The gate measures something real. It has no checks of its own; it passes
only when every existing CI job reported `success`:

  needs: [test, lint, coverage, security]   # if: always()

and it prints its denominator ("checked 4 of 4 expected CI jobs"). The
`EXPECTED` list is asserted against `needs` in both directions: a job in
EXPECTED but absent from needs fails as MISSING, a job in needs but not
in EXPECTED fails as UNGUARDED, and zero jobs inspected is an explicit
refusal to report a pass. So the gate cannot quietly shrink to guarding
less than it claims. `skipped` is not a pass either — only `success` is.

Falsified locally against six inputs before pushing: all-green passes;
one failure, one skip, a missing job, an empty needs, and an extra
unguarded job each fail.

`runs-on: ubuntu-latest` matches the four jobs it aggregates — not bare
`self-hosted`, which would match every self-hosted runner the org
registers including the aarch64 gx10 training node (paiml/infra#342).

Triggers are inherited from ci.yml: pull_request and push to main (this
repo's default branch).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: clear the 5 months of CI bit-rot the new `gate` surfaced

The `gate` job added in the previous commit did what it was built to do
on its first run: it went red, because two of the four CI jobs it
aggregates are genuinely failing.

Neither failure is caused by this branch — it touched only ci.yml. Main's
last CI run was 2026-04-06 (green, e67a0d4) and nothing has run on main
since. Both jobs pin rolling inputs, so both rotted unobserved for five
months:

  Lint     `dtolnay/rust-toolchain@stable` is now clippy 1.98
  Security `cargo audit` fetches the advisory DB at run time

Lint — two new-in-1.98 lints, both behaviour-preserving rewrites:

  adapters/wos.rs:312  collapsible_match   → `Signal::Cont if …` guard.
                       Non-Stopped Cont still falls through to `_ => {}`.
  metrics.rs:156       manual_checked_ops  → `checked_div(count)` +
                       `map_or(Duration::ZERO, …)`. count == 0 still
                       yields ZERO; the extra relaxed load is side-effect
                       free.

Security — 2 vulnerabilities, both semver-compatible patch bumps:

  crossbeam-epoch 0.9.18 → 0.9.20  RUSTSEC-2026-0204
  h2              0.4.13 → 0.4.19  RUSTSEC-2026-0258

The crossbeam-epoch bump is the same one PR #13 carries; #13 is the PR
that has been sitting BLOCKED against a green board this whole time.
Only those two packages were relocked. The 8 remaining advisories are
already-allowed `unmaintained`/`unsound` warnings, untouched.

Also refactors `WosAdapter::status`, which the pmat pre-commit hook
rejected at Cognitive 45 > 25. Measured before touching it: the
violation is entirely pre-existing and in a function this branch had no
reason to edit — the hook only scans STAGED files, so `status` had never
been weighed. The one-line lint fix above is what put wos.rs in the
staged set. That fix on its own moved the file 126 → 125 cognitive.

The 45 was nesting, not logic, so `status` splits into three helpers
with the branch structure preserved exactly:

  query_wos_ctl_status()    Ok(None) = "no answer, fall back to local
                            state"; a non-zero wos-ctl exit is an
                            ANSWER (Stopped), and that distinction is
                            the one thing easy to lose here.
  parse_wos_ctl_status()    pure str → Option<DaemonStatus>
  status_from_process_state()  pure ProcessState → DaemonStatus

wos.rs now reports no complexity violation at all. The two pure helpers
are directly unit-testable, which the nested chain was not.

Verified locally: `cargo fmt --all -- --check` clean, `cargo clippy
--workspace -- -D warnings` clean, `cargo test --workspace` 932 passed /
0 failed — the same 932 as before the refactor.

Deliberately NOT fixed: `manager.rs:94` trips
`clippy::duration_suboptimal_units` on local clippy 1.97 but NOT on CI's
1.98, which reported exactly two errors. Chasing it would fix a lint the
gate never asked for. That the two toolchains disagree in both
directions is the real hazard of `@stable` + `-D warnings`, and is worth
a follow-up pin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(lint): restore the deliberate `unused_async` allows under clippy 1.98

Third and last layer of the same bit-rot. `cargo clippy` stops at the
first crate that fails, so each fix only revealed the next crate:

  run 1  duende-core    collapsible_match, manual_checked_ops
  run 2  duende-test    unused_async_trait_impl  ×2
  now    duende-observe unused_async_trait_impl  ×2

All four remaining sites are the same defect, and it is not a code
defect. Each already carried a deliberate, commented
`#[allow(clippy::unused_async)]` — the `async` is intended API surface
("Will be async when actually spawning chaos threads"). clippy 1.98
split that case out into `clippy::unused_async_trait_impl`, so the
existing allows stopped covering their own documented intent.

Fix is to allow the new name, NOT to change the signatures. Clippy's own
suggestion — rewrite `pub async fn start(&mut self) -> Result<()>` as
`pub fn start(&mut self) -> impl Future<Output = Result<()>>` — would
churn public API in four places to silence a lint the authors had
already considered and rejected.

`#[allow(unknown_lints)]` accompanies it because the new name does not
exist before clippy 1.98, where `-D warnings` turns an unknown lint into
a hard error. Measured, not assumed: the first attempt used
`#[cfg_attr(clippy, allow(...))]` and clippy rejected THAT two ways at
once —

  error: no need to put clippy lints behind a `clippy` cfg
  error: unknown lint: `clippy::unused_async_trait_impl`

so the file now builds clean on both 1.97 and 1.98.

Verified with CI's exact toolchain, installed locally to stop guessing
at it (`rustup toolchain install 1.98.0`), running CI's exact commands:

  cargo +1.98.0 fmt --all -- --check         clean
  cargo +1.98.0 clippy --workspace -- -D warnings   clean, whole workspace
  cargo +1.98.0 test --workspace             932 passed / 0 failed
  cargo clippy (1.97) --workspace            still clean

That last line is the portability check: this repo pins
`dtolnay/rust-toolchain@stable`, so the lint set moves under it without
a commit. 1.97 and 1.98 disagree in BOTH directions here — 1.97 alone
flags `manager.rs:94` (`duration_suboptimal_units`), 1.98 alone flags
these four. Pinning the toolchain is the real fix and is worth a
follow-up; this commit just gets the gate honest and green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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