From e0b5a5a41cd0b8dd7dee3589b752039edd4d13a8 Mon Sep 17 00:00:00 2001 From: baladithyab Date: Mon, 17 Aug 2026 23:00:28 -0700 Subject: [PATCH 1/3] fix(deps): green the cargo audit gate on origin/master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cargo audit job has been failing on origin/master since at least 2026-08-15 (runs on bd58cec), so every PR inherits a red check that carries no signal. Seed audio-graph-d275 records the root cause: 942a's remediation is reachable only from integration/session-memory-wave-20260814, never from master. RUSTSEC-2026-0213 (ammonia 4.1.3 <- surrealdb-core <- surrealdb) had a real fix available, so it gets a version bump, not an ignore: ammonia 4.1.3 -> 4.1.4 via cargo update -p ammonia. Exactly one package moved; no other lockfile churn. RUSTSEC-2026-0235 (rkyv 0.7.46 <- rust_decimal 1.42.1) cannot be upgraded — patched 0.8.17 is semver-incompatible with rust_decimal's optional ^0.7.46 requirement — so it must be an ignore. Rather than author a fresh justification, this ports the reviewed stanza from integration/session-memory-wave-20260814 verbatim, after re-confirming its central claim on this branch: cargo tree --locked --offline -i rkyv@0.7.46 --target all --all-features --edges all prints no reverse dependency, so the optional edge is genuinely inactive. Scope: src-tauri/.cargo/audit.toml and src-tauri/Cargo.lock only. Verified independently: cargo audit exits 0 with only the 4 pre-existing allowed warnings; the baseline was reproduced from origin/master's own lockfile and audit.toml to confirm both advisories were present before and absent after; audit.toml contains no 0213 entry, proving the bump rather than a paper-over; cargo check --locked --features cloud and fmt --check both pass. Two honest scope notes. The cloud feature set does not compile ammonia at all (it enters only via the optional surrealdb-embedded feature), so ammonia 4.1.4 was built separately to confirm it compiles. And ci/storage-probe/Cargo.lock still pins ammonia 4.1.2 and rkyv 0.7.46; CI audits only src-tauri, and the ported stanza disclaims that graph as owned by seed audio-graph-c65d, so this change greens the CI gate without claiming repo-wide audit cleanliness. Co-Authored-By: Claude Opus 5 (1M context) --- src-tauri/.cargo/audit.toml | 22 ++++++++++++++++++++++ src-tauri/Cargo.lock | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src-tauri/.cargo/audit.toml b/src-tauri/.cargo/audit.toml index 3b593823..6b682512 100644 --- a/src-tauri/.cargo/audit.toml +++ b/src-tauri/.cargo/audit.toml @@ -65,6 +65,28 @@ ignore = [ "RUSTSEC-2025-0100", "RUSTSEC-2025-0119", + # ── Resolver-retained rust_decimal rkyv 0.7 edge (inactive) ───── + # Source: Cargo.lock retains rust_decimal 1.42.1's optional + # `rkyv = "^0.7.46"` dependency even though no AudioGraph feature enables it. + # Blocker: rust_decimal 1.42.1 requires optional rkyv ^0.7.46; patched rkyv + # 0.8.17 is semver-incompatible with that requirement. Manual lock-stanza + # pruning is resolver-unstable because Cargo retains/re-adds the declared + # optional edge. Seed audio-graph-c65d separately owns the independent + # ci/storage-probe lock graph; its resolution is not covered by this ignore. + # Crate: rkyv Title: Insufficient archive validation can cause out-of-bounds + # reads in archives containing Rc/Arc. + # Reachability: `cargo tree --locked --offline -i rkyv@0.7.46 --target all + # --all-features --edges all` prints no reverse dependency; default and + # cloud-only resolution do not contain the package at all. Therefore the + # affected checked archive-access/deserialization APIs are not compiled into + # any current AudioGraph feature set. + # Risk acceptance: lockfile-scanner finding only while that edge stays + # inactive. Do not use this exception if a feature activates rkyv 0.7. + # Remediation: remove immediately if any default/cloud/all-features tree makes + # the command above non-empty. Otherwise remove when rust_decimal drops or + # raises the optional 0.7 requirement so a targeted lock update prunes it. + "RUSTSEC-2026-0235", # rkyv 0.7.46: inactive resolver-retained optional edge + # ── SurrealDB embedded adapter (gated, non-default, conformance-only) ── # Source: transitive via the optional `surrealdb-embedded` feature → # surrealdb 3.1.x → rsa 0.9.10 (pulled by surrealdb's RPC/auth stack). diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7247d3af..4771b76d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "ammonia" -version = "4.1.3" +version = "4.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b9d3370580a12f4b7a10fdcc18b28942c083ba570e3d954fe59d10951b85a2" +checksum = "dc6d763210e2eb7670d1a5183a08bebefa3f97db2a738a684f2ce00bd49f681d" dependencies = [ "cssparser 0.37.0", "html5ever 0.39.0", From 8995bc9cbc6f9b357fcfc7016dd1250e8f35bfdb Mon Sep 17 00:00:00 2001 From: baladithyab Date: Mon, 17 Aug 2026 23:07:40 -0700 Subject: [PATCH 2/3] ci: enforce the rkyv 0.7 audit ignore's reachability condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex raised a P2 on PR #101: `ignore` in audit.toml is an unconditional advisory-ID suppression, so the RUSTSEC-2026-0235 stanza — whose justification is "this is an inactive resolver-retained optional edge" and whose stated remediation trigger is "remove immediately if any tree makes cargo tree -i non-empty" — would keep passing after rkyv 0.7 became reachable. The condition was documented and unenforced, which under this repo's evidence rules is an unverified claim rather than a control. Assert it in the audit job instead of trusting a reader to re-run the command by hand. cargo tree -i prints the reverse-dependency tree on stdout and only a "nothing to print" warning on stderr, so an anchored root-line match on stdout is the reachability signal. Verified in both directions before committing: the pattern matches the root line of a genuinely reachable crate (serde, 119 stdout lines) and does not match for rkyv 0.7.46 today, so the check can actually fail rather than passing unconditionally. actionlint clean. This expands the PR's scope to a third file. Justified because the ignore landed in the same PR is incomplete without it. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0dd636c..e9019d82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,6 +129,30 @@ jobs: working-directory: audio-graph/src-tauri run: cargo audit + # `ignore` in audit.toml is an unconditional advisory-ID suppression, so a + # stanza whose justification is "this package is unreachable" would keep + # passing after the package became reachable. The RUSTSEC-2026-0235 + # (rkyv 0.7.46) stanza states exactly that condition and names this command + # as its own remediation trigger, so assert it here rather than trusting a + # reader to re-run it by hand. + # + # `cargo tree -i` prints the reverse-dependency tree on stdout and only a + # "nothing to print" warning on stderr, so stdout mentioning the crate IS + # the reachability signal. Verified in both directions: this prints 0 + # matching lines for rkyv today and 119 for a reachable crate. + - name: Assert the rkyv 0.7 audit ignore is still unreachable + working-directory: audio-graph/src-tauri + run: | + if cargo tree --locked -i rkyv@0.7.46 \ + --target all --all-features --edges all 2>/dev/null \ + | grep -q '^rkyv v0\.7\.'; then + echo "::error::RUSTSEC-2026-0235's ignore in .cargo/audit.toml is justified only while rkyv 0.7 is an inactive resolver-retained edge, but it is now reachable." + echo "::error::Remove that ignore and resolve the advisory, or replace its justification. Reverse-dependency tree follows." + cargo tree --locked -i rkyv@0.7.46 --target all --all-features --edges all || true + exit 1 + fi + echo "rkyv 0.7 remains unreachable; the RUSTSEC-2026-0235 ignore stays justified." + # ── Rust backend — Linux ─────────────────────────────────────────── # Tests use `tauri::test::mock_context` + `noop_assets` + `any_thread()` # in src/speech/tests_integration.rs. Even with MockRuntime, tao's Linux From 4c123798a455609b4b5e6739a8f9ad20bb0c8885 Mon Sep 17 00:00:00 2001 From: baladithyab Date: Mon, 17 Aug 2026 23:12:37 -0700 Subject: [PATCH 3/3] ci: match the rkyv audit assertion to the advisory's affected range CodeRabbit found a hole in the check added in the previous commit: it keyed on the pinned rkyv@0.7.46, but RUSTSEC-2026-0235's patched range is ">= 0.8.17". A lockfile that later resolved 0.7.47 or 0.8.10 would leave a still-vulnerable package in the tree, still suppressed by the ID-level ignore, while the reachability assertion found nothing and passed. The narrow check would have given false assurance in exactly the drift scenario it exists to catch. Scan the forward tree for any rkyv below 0.8.17 instead. Version comparison was unit-checked against synthetic input before landing: 0.7.46 and 0.8.16 flag; 0.8.17, 0.9.0, and 1.0.0 do not. Against the real tree it reports 0 affected nodes, matching the ported stanza's claim. actionlint clean. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9019d82..1aeb347a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -136,22 +136,35 @@ jobs: # as its own remediation trigger, so assert it here rather than trusting a # reader to re-run it by hand. # - # `cargo tree -i` prints the reverse-dependency tree on stdout and only a - # "nothing to print" warning on stderr, so stdout mentioning the crate IS - # the reachability signal. Verified in both directions: this prints 0 - # matching lines for rkyv today and 119 for a reachable crate. - - name: Assert the rkyv 0.7 audit ignore is still unreachable + # Matched against the advisory's AFFECTED RANGE (patched is ">= 0.8.17"), + # not a pinned version: a check keyed on rkyv@0.7.46 alone would pass + # silently if the lockfile later resolved 0.7.47 or 0.8.10, both still + # vulnerable and both still suppressed by the ID-level ignore. + # + # Version logic unit-checked against synthetic input before landing: + # 0.7.46 and 0.8.16 flag; 0.8.17, 0.9.0, and 1.0.0 do not. + - name: Assert no affected rkyv is reachable working-directory: audio-graph/src-tauri run: | - if cargo tree --locked -i rkyv@0.7.46 \ - --target all --all-features --edges all 2>/dev/null \ - | grep -q '^rkyv v0\.7\.'; then - echo "::error::RUSTSEC-2026-0235's ignore in .cargo/audit.toml is justified only while rkyv 0.7 is an inactive resolver-retained edge, but it is now reachable." - echo "::error::Remove that ignore and resolve the advisory, or replace its justification. Reverse-dependency tree follows." - cargo tree --locked -i rkyv@0.7.46 --target all --all-features --edges all || true + affected="$( + cargo tree --locked --target all --all-features --edges all \ + --format '{p}' --prefix none 2>/dev/null \ + | awk ' + $1 == "rkyv" { + v = $2; sub(/^v/, "", v); + split(v, p, "."); + if ((p[1]+0) == 0 && ((p[2]+0) < 8 || ((p[2]+0) == 8 && (p[3]+0) < 17))) + print $1 " " $2; + }' \ + | sort -u + )" + if [ -n "$affected" ]; then + echo "::error::RUSTSEC-2026-0235's ignore in .cargo/audit.toml is justified only while no affected rkyv (< 0.8.17) is reachable, but one now is:" + printf '%s\n' "$affected" + echo "::error::Remove that ignore and resolve the advisory, or replace its justification with one that matches reality." exit 1 fi - echo "rkyv 0.7 remains unreachable; the RUSTSEC-2026-0235 ignore stays justified." + echo "No affected rkyv (< 0.8.17) is reachable; the RUSTSEC-2026-0235 ignore stays justified." # ── Rust backend — Linux ─────────────────────────────────────────── # Tests use `tauri::test::mock_context` + `noop_assets` + `any_thread()`