From 56126122ef9c58c56e8d602f95fdde4f6579f0b6 Mon Sep 17 00:00:00 2001 From: Anthony Ronning <101225832+AnthonyRonning@users.noreply.github.com> Date: Mon, 26 Oct 2026 14:24:26 +0000 Subject: [PATCH 1/2] chore(agent): prepare 0.0.8 release --- apps/maple-agent/Cargo.lock | 16 ++++++++-------- apps/maple-agent/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/maple-agent/Cargo.lock b/apps/maple-agent/Cargo.lock index 46f7bba71..29169cbad 100644 --- a/apps/maple-agent/Cargo.lock +++ b/apps/maple-agent/Cargo.lock @@ -5766,7 +5766,7 @@ dependencies = [ [[package]] name = "maple-agent" -version = "0.0.7" +version = "0.0.8" dependencies = [ "agent-client-protocol", "anyhow", @@ -5818,7 +5818,7 @@ dependencies = [ [[package]] name = "maple-agent-app" -version = "0.0.7" +version = "0.0.8" dependencies = [ "axum", "base64 0.22.1", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "maple-agent-updater" -version = "0.0.7" +version = "0.0.8" dependencies = [ "anyhow", "base64 0.22.1", @@ -5902,7 +5902,7 @@ dependencies = [ [[package]] name = "maple-billing" -version = "0.0.7" +version = "0.0.8" dependencies = [ "reqwest 0.13.4", "serde", @@ -7680,7 +7680,7 @@ dependencies = [ [[package]] name = "pi-agent-core" -version = "0.0.7" +version = "0.0.8" dependencies = [ "async-trait", "futures-util", @@ -7693,7 +7693,7 @@ dependencies = [ [[package]] name = "pi-ai" -version = "0.0.7" +version = "0.0.8" dependencies = [ "async-trait", "bytes", @@ -7710,7 +7710,7 @@ dependencies = [ [[package]] name = "pi-coding-agent" -version = "0.0.7" +version = "0.0.8" dependencies = [ "async-trait", "base64 0.22.1", @@ -10103,7 +10103,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "store-bench" -version = "0.0.7" +version = "0.0.8" dependencies = [ "anyhow", "maple-agent", diff --git a/apps/maple-agent/Cargo.toml b/apps/maple-agent/Cargo.toml index b750b315f..56bd90534 100644 --- a/apps/maple-agent/Cargo.toml +++ b/apps/maple-agent/Cargo.toml @@ -4,7 +4,7 @@ members = ["crates/maple-agent", "crates/maple-billing", "crates/maple-agent-upd [workspace.package] edition = "2024" -version = "0.0.7" +version = "0.0.8" license = "MIT" [workspace.dependencies] From 688667db5d7d1c92bfb5e0d0d734844f8e20f6ec Mon Sep 17 00:00:00 2001 From: Anthony Ronning <101225832+AnthonyRonning@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:59:09 +0000 Subject: [PATCH 2/2] fix(agent): document native zstd advisory exceptions --- apps/maple-agent/deny.toml | 20 +++++++ apps/maple-agent/docs/zstd-advisories.md | 70 ++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 apps/maple-agent/docs/zstd-advisories.md diff --git a/apps/maple-agent/deny.toml b/apps/maple-agent/deny.toml index 123a9fdae..0a6ae4cd7 100644 --- a/apps/maple-agent/deny.toml +++ b/apps/maple-agent/deny.toml @@ -9,6 +9,26 @@ all-features = true # notices are tracked separately because they often require API migrations. unsound = "all" unmaintained = "none" +# Native Agent reachability review: docs/zstd-advisories.md. These exceptions +# cover only the listed findings in zstd 0.13.3 / zstd-safe 7.2.4 / zstd-sys +# 2.1.0, used by the store codec and pinned CUA cursor-overlay. Re-review on +# dependency/pin, feature, call-site, or target changes; remove after upgrading. +ignore = [ + { id = "RUSTSEC-2026-0391", reason = "Both consumers create fresh owned contexts; borrowed with_context reuse is unused" }, + { id = "RUSTSEC-2026-0395", reason = "StableInBuffer is never enabled; ordinary encoders select only CompressionLevel" }, + { id = "RUSTSEC-2026-0396", reason = "Seekable and seek-table APIs and the seekable feature are unused" }, + { id = "RUSTSEC-2026-0397", reason = "Consumers use OutBuffer::around at position zero, not around_pos beyond an initialized Vec" }, + { id = "RUSTSEC-2026-0398", reason = "No seekable decompression or caller-selected seek offsets" }, + { id = "RUSTSEC-2026-0399", reason = "No experimental init_using_cdict/init_using_ddict or borrowed prepared dictionaries" }, + { id = "RUSTSEC-2026-0400", reason = "No context mixes one-shot low-level calls with an unfinished stream" }, + { id = "RUSTSEC-2026-0401", reason = "Dictionary training is unused; no untrusted sample-size arrays reach train_from_buffer" }, + { id = "RUSTSEC-2026-0402", reason = "No CCtx::try_clone or NbWorkers setting; experimental and zstdmt features are unused" }, + { id = "RUSTSEC-2026-0403", reason = "Both consumers use read::Decoder, explicitly excluded by the advisory; initialized slice output is used" }, + { id = "RUSTSEC-2026-0404", reason = "No experimental DCtx::try_clone or prepared-dictionary cloning" }, + { id = "RUSTSEC-2026-0405", reason = "No SeekableCStream API or invalid caller-selected InBuffer position" }, + { id = "RUSTSEC-2026-0406", reason = "Only fresh single-worker contexts are configured before streaming; no unfinished multithreaded frame" }, + { id = "RUSTSEC-2026-0410", reason = "The faulty allocator shim is wasm32-only; Agent targets native macOS, Linux and Windows" }, +] [bans] # Emergency supply-chain containment for the August 2026 crates.io campaign. diff --git a/apps/maple-agent/docs/zstd-advisories.md b/apps/maple-agent/docs/zstd-advisories.md new file mode 100644 index 000000000..4922318e7 --- /dev/null +++ b/apps/maple-agent/docs/zstd-advisories.md @@ -0,0 +1,70 @@ +# Native Agent zstd advisory exceptions + +The exceptions in `../deny.toml` apply to the 14 findings below, reviewed against +`zstd 0.13.3`, `zstd-safe 7.2.4`, and `zstd-sys 2.1.0+zstd.1.5.7` on the native +macOS, Linux, and Windows targets. Other vulnerability/unsoundness findings and +the package bans remain blocking. This policy does not apply to Maple Research's +separate graph. + +These are real upstream defects. Source review found no triggering path in the +Agent's selected APIs, features, context state, and native platforms. This is a +bounded reachability assessment, not an exploit test or a claim that all uses of +these dependency versions are safe. The patched upstream versions are +`zstd 0.14.3`, `zstd-safe 8.2.0`, and `zstd-sys 2.1.2`. + +## Reviewed consumers + +The Agent lockfile has exactly two direct zstd consumers and no independent +zstd-safe or zstd-sys consumer: + +- [`store/codec.rs`](../crates/maple-agent/src/store/codec.rs) uses + `stream::encode_all(bytes, 3)` and `stream::read::Decoder::new`, with a bounded + read into a separate caller-owned vector. Each operation creates a fresh owned + context. Attachment-migration tests also use `encode_all`. +- CUA `cursor-overlay`, pinned at + [`2a3975570a885f45ef83f7e81bba54a01804ebd0`](https://github.com/trycua/cua/blob/2a3975570a885f45ef83f7e81bba54a01804ebd0/libs/cua-driver/rust/crates/cursor-overlay/src/theme_artifact.rs#L294-L350), + uses `encode_all` at level 12 for theme authoring and `read::Decoder` for theme + loading. Custom themes can be external files; the assessment does not assume + that compressed inputs are trusted. + +Both dependencies request ordinary zstd features. `experimental`, `seekable`, +and `zstdmt` are not requested. Dictionary-building support is enabled by +default, but neither consumer calls its training API. The selected decoding +adapter creates valid input buffers and initialized slice output at position +zero; it does not supply an uninitialized caller vector to zstd-safe. Encoding +uses its internal output vector safely at position zero. + +## Finding-specific rationale + +The links pin the reviewed RustSec database snapshot, rather than treating an +advisory's package-version match as proof of a reachable product defect. + +| Advisory | Required path or state absent from the reviewed Agent | +| --- | --- | +| [0391](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd/RUSTSEC-2026-0391.md) | Borrowed `with_context` reuse. Both consumers create fresh owned contexts; `encode_all` finishes its stream. | +| [0395](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0395.md) | Enabling `StableInBuffer`. The ordinary encoders select only the compression level. | +| [0396](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0396.md) | Seekable decoding or seek-table access. These APIs and the feature are unused. | +| [0397](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0397.md) | `OutBuffer::around_pos` with a gap beyond an initialized vector. The selected adapters use `around` at position zero. | +| [0398](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0398.md) | Seekable decompression with a caller-selected offset. Neither consumer uses it. | +| [0399](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0399.md) | Experimental borrowed prepared-dictionary initialization. Ordinary wrappers load empty dictionary bytes into fresh contexts instead. | +| [0400](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0400.md) | Mixing low-level one-shot methods with an unfinished stream on the same context. `encode_all` is internally streaming and does not do this. | +| [0401](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0401.md) | Dictionary training using untrusted sample-size arrays. The available training API is never called. | +| [0402](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0402.md) | Experimental `CCtx::try_clone` with multithreaded context state. No clone or `NbWorkers` setting is used. | +| [0403](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0403.md) | The generic decompression method is reached, but the vulnerable vector-output path is absent. The advisory explicitly excludes `read::Decoder`; its reader uses an initialized slice and propagates errors before returning written bytes. | +| [0404](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0404.md) | Experimental `DCtx::try_clone`, dictionary/prefix cloning, or mid-frame cloning. These APIs are unused. | +| [0405](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0405.md) | Seekable compression with an invalid caller-selected input-buffer position. The seekable API is unused. | +| [0406](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-safe/RUSTSEC-2026-0406.md) | Changing a context with an unfinished multithreaded frame. Settings are applied only to fresh single-worker contexts before streaming. | +| [0410](https://github.com/RustSec/advisory-db/blob/a78282a1414d6c28cc228c4eae3570451affb0dc/crates/zstd-sys/RUSTSEC-2026-0410.md) | The affected allocator module is compiled only for `wasm32`. The supported Agent targets are native. | + +## Re-review and removal + +Re-review the complete exception list whenever either consumer, the CUA revision, +the resolved compression versions/features, or the supported target list changes. +In particular, borrowed context reuse, write-side decoders, dictionary training, +prepared dictionaries, seekable/experimental APIs, context cloning, worker +configuration, or a Wasm target invalidate the relevant reasoning above. + +Remove each exception once all affected locked packages have been upgraded to +patched versions. Run `scripts/audit-sqlcipher-dependencies.py` against a current +advisory database for each supported target after changing this policy. Keep new +advisories blocking; these entries do not authorize accepting future findings.