Skip to content

ci(rs): add cargo-deny and resolve outstanding advisories#1486

Merged
kixelated merged 4 commits into
mainfrom
claude/goofy-merkle-ed0c4e
May 24, 2026
Merged

ci(rs): add cargo-deny and resolve outstanding advisories#1486
kixelated merged 4 commits into
mainfrom
claude/goofy-merkle-ed0c4e

Conversation

@kixelated
Copy link
Copy Markdown
Collaborator

Summary

  • Adds cargo-deny to the Nix dev shell and wires cargo deny check into just rs check (and just rs ci) for license / advisory / source / ban policy enforcement on every PR.
  • Adds a just rs deny-reminder recipe that prints active advisory ignores with their inline rationale after each run, so deferred items don't get forgotten. cargo-deny's native ignored-advisory notes only surface at --log-level=info, which dumps full dep trees and is too noisy for CI.
  • Initial cargo-deny run surfaced 9 findings; this PR resolves 5 of them.

Findings resolved

Advisory Fix
RUSTSEC-2026-0119 (hickory-proto CPU exhaustion) Bumped web-transport-iroh = "0.5", pulls hickory 0.26.1
RUSTSEC-2026-0120 (hickory-net DNSSEC infinite loop) Same upgrade
RUSTSEC-2023-0089 (atomic-polyfill) Dropped transitively by the iroh upgrade
RUSTSEC-2025-0134 (rustls-pemfile unmaintained) Migrated moq-native to rustls::pki_types::pem::PemObject (the upstream-recommended replacement); 5 call sites across client.rs, server.rs, tls.rs, quiche.rs
paste via mp4-atom Bumped mp4-atom = "0.11" (uses pastey); small API fix for the new Moov.ainf field

Findings ignored (with rationale)

Each has an inline comment in deny.toml naming the upstream blocker so it's clear when the ignore can be removed:

  • RUSTSEC-2023-0071 (rsa Marvin Attack) — the rsa crate is unreachable for us: moq-token uses it only for keygen + JWK component serialization, while signing runs through jsonwebtoken backed by aws-lc-rs (constant time). Vulnerable code path is not exercised.
  • RUSTSEC-2024-0320 (yaml-rust via foundations → tokio-quiche)
  • RUSTSEC-2024-0436 (paste via gstreamer 0.23; 0.25 drops it but requires Rust 1.92 vs our 1.85 MSRV) — build-time proc-macro only
  • RUSTSEC-2025-0141 (bincode 1.x via http-cache-reqwest)

Test plan

  • cargo deny check reports advisories ok, bans ok, licenses ok, sources ok
  • cargo check --workspace --all-features (sans moq-gst, which needs GStreamer system deps) builds cleanly
  • cargo test -p moq-native --all-features — 92 tests pass
  • cargo test -p moq-mux -p moq-token — 240 tests pass
  • cargo fmt --all --check, cargo shear, cargo sort --workspace --check
  • Full nix develop --command just rs ci in CI

(Written by Claude)

Adds cargo-deny to the Nix dev shell and wires `cargo deny check`
into `just rs check` (and thus `just rs ci`) so license, advisory,
source, and ban policy is enforced on every PR. The new deny-reminder
recipe prints active advisory ignores with their inline rationale
after each run so they don't get forgotten; cargo-deny's native
ignored-advisory notes only surface at info log level.

Initial run surfaced 9 findings; this commit resolves 5 of them:

- Bump web-transport-iroh 0.4 -> 0.5 to pull hickory 0.26.1, fixing
  RUSTSEC-2026-0119 (hickory-proto CPU exhaustion) and
  RUSTSEC-2026-0120 (hickory-net DNSSEC infinite loop). Drops
  atomic-polyfill (RUSTSEC-2023-0089) transitively.

- Migrate moq-native off the unmaintained rustls-pemfile crate
  (RUSTSEC-2025-0134) to the rustls-pki-types `PemObject` trait,
  the upstream-recommended replacement.

- Bump mp4-atom 0.10 -> 0.11 so moq-mux pulls pastey (maintained)
  rather than paste via mp4-atom. paste is still pulled by
  gstreamer 0.23 (whose 0.25 release requires Rust 1.92, beyond
  our 1.85 MSRV); RUSTSEC-2024-0436 stays in the ignore list.
  0.11 adds a Moov.ainf field; default to None.

The four remaining ignores (rsa 0.9 Marvin Attack, yaml-rust via
foundations/tokio-quiche, paste via gstreamer, bincode 1.x via
http-cache) each have an inline rationale in deny.toml naming the
upstream blocker. rsa is unreachable for us: moq-token uses it only
for keygen and JWK component serialization, while signing runs
through jsonwebtoken backed by aws-lc-rs (constant time).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

Review Change Stack

Warning

Review limit reached

@kixelated, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 4 reviews/hour. Refill in 2 minutes and 53 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9e7d539a-6319-4c5a-a302-29de5b89fe33

📥 Commits

Reviewing files that changed from the base of the PR and between 6b90ae0 and 18bbf95.

📒 Files selected for processing (1)
  • rs/moq-native/src/client.rs

Walkthrough

This PR introduces three independent bodies of work: (1) cargo-deny security audit infrastructure, including configuration, documentation, and integration into the development and verification workflows; (2) dependency updates to mp4-atom (0.10.0 → 0.11) and web-transport-iroh (0.4 → 0.5), plus a field initialization change in FMP4 single-moov segment construction; and (3) a systematic migration of TLS/PEM parsing across four modules (client, quiche, server, and general) from rustls_pemfile to rustls pki_types APIs, removing the rustls_pemfile dependency entirely.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ci(rs): add cargo-deny and resolve outstanding advisories' directly and concisely summarizes the main changes: adding cargo-deny tooling and resolving security advisories.
Description check ✅ Passed The description comprehensively explains the changes, findings resolved, findings ignored with rationale, and test plan, all directly related to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/goofy-merkle-ed0c4e
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/goofy-merkle-ed0c4e

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

kixelated added 2 commits May 24, 2026 11:02
`cargo deny check --show-stats` already prints the notes count;
the extra reminder block was more noise than signal.
When CodeRabbit's hourly quota or org credits are exhausted, it
posts a "review limit reached" comment instead of an actual
review. Document running `/review` locally as the fallback so
PRs don't sit unreviewed waiting for the quota to refill.
@kixelated kixelated enabled auto-merge (squash) May 24, 2026 18:05
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rs/moq-native/src/client.rs (1)

135-139: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Load every certificate from each root PEM file.

Line 135 now takes only the first certificate from each --tls-root file. That silently drops the rest of a CA bundle and can break custom trust stores. It also differs from rs/moq-native/src/server.rs Line 82 and rs/moq-native/src/tls.rs Line 112, which both collect every PEM certificate.

Suggested fix
-				let cert = CertificateDer::pem_reader_iter(&mut reader)
-					.next()
-					.context("no roots found")?
-					.context("failed to read root cert")?;
-				roots.add(cert).context("failed to add root cert")?;
+				let certs: Vec<CertificateDer<'static>> = CertificateDer::pem_reader_iter(&mut reader)
+					.collect::<Result<_, _>>()
+					.context("failed to read root cert")?;
+				anyhow::ensure!(!certs.is_empty(), "no roots found");
+				for cert in certs {
+					roots.add(cert).context("failed to add root cert")?;
+				}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rs/moq-native/src/client.rs` around lines 135 - 139, The code only reads the
first certificate from CertificateDer::pem_reader_iter(&mut reader) and drops
the rest of the PEM file; change it to iterate over all certificates returned by
CertificateDer::pem_reader_iter, adding each parsed cert to roots (using
roots.add(cert) for every item) and propagate/context errors per-certificate
(e.g., "no roots found" only if iterator yields nothing, and "failed to read
root cert"/"failed to add root cert" for individual certs) so the entire CA
bundle is loaded rather than only the first cert.
🧹 Nitpick comments (1)
deny.toml (1)

55-55: ⚡ Quick win

Consider stricter enforcement for duplicate versions.

multiple-versions = "warn" permits duplicate dependency versions without blocking the build. Setting it to "deny" would enforce a cleaner dependency tree and catch version conflicts earlier.

📦 Stricter duplicate-version enforcement
-multiple-versions = "warn"
+multiple-versions = "deny"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deny.toml` at line 55, Update the deny configuration to reject duplicate
dependency versions by changing the "multiple-versions" setting from "warn" to
"deny" in the deny.toml; locate the "multiple-versions" key and set its value to
"deny" so the build fails on duplicate versions instead of only warning,
ensuring stricter enforcement of dependency version conflicts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@rs/moq-native/src/client.rs`:
- Around line 135-139: The code only reads the first certificate from
CertificateDer::pem_reader_iter(&mut reader) and drops the rest of the PEM file;
change it to iterate over all certificates returned by
CertificateDer::pem_reader_iter, adding each parsed cert to roots (using
roots.add(cert) for every item) and propagate/context errors per-certificate
(e.g., "no roots found" only if iterator yields nothing, and "failed to read
root cert"/"failed to add root cert" for individual certs) so the entire CA
bundle is loaded rather than only the first cert.

---

Nitpick comments:
In `@deny.toml`:
- Line 55: Update the deny configuration to reject duplicate dependency versions
by changing the "multiple-versions" setting from "warn" to "deny" in the
deny.toml; locate the "multiple-versions" key and set its value to "deny" so the
build fails on duplicate versions instead of only warning, ensuring stricter
enforcement of dependency version conflicts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 35441a19-0104-471e-b327-0edacc9450d9

📥 Commits

Reviewing files that changed from the base of the PR and between aacba0d and 6b90ae0.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • CLAUDE.md
  • Cargo.toml
  • deny.toml
  • flake.nix
  • rs/justfile
  • rs/moq-mux/Cargo.toml
  • rs/moq-mux/src/container/fmp4/import.rs
  • rs/moq-native/Cargo.toml
  • rs/moq-native/src/client.rs
  • rs/moq-native/src/quiche.rs
  • rs/moq-native/src/server.rs
  • rs/moq-native/src/tls.rs
💤 Files with no reviewable changes (1)
  • rs/moq-native/Cargo.toml

The client root cert loader was discarding every certificate after
the first one in each PEM file, so a multi-cert CA bundle would
silently lose its other entries. Bug predates this branch but the
PemObject migration left it untouched; aligning now with the
collect-all pattern already used in server.rs and tls.rs.
@kixelated kixelated merged commit 0fc1704 into main May 24, 2026
1 check passed
@kixelated kixelated deleted the claude/goofy-merkle-ed0c4e branch May 24, 2026 18:27
@moq-bot moq-bot Bot mentioned this pull request May 24, 2026
kixelated added a commit that referenced this pull request May 24, 2026
`cargo deny` (added in #1486) flags audiopus_sys as unmaintained:
last commit 5 years ago, maintainer unresponsive to PRs fixing the
exact CMake 4 issue we already work around with
CMAKE_POLICY_VERSION_MINIMUM=3.5. There's no safe upgrade and the
candidate replacements (`magnum-opus`/`opusic-sys`) all wrap the
same vendored libopus, so swapping doesn't fix the underlying
problem.

Add the advisory to deny.toml's ignore list with rationale. Drop
when libopus's CMakeLists gets updated upstream or a maintained
opus binding emerges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@moq-bot moq-bot Bot mentioned this pull request May 24, 2026
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