# cargo-deny configuration — supply-chain advisory policy. # # Run: `cargo deny check advisories` # # This file exists to make Aivyx's supply-chain decisions durable and # reviewable (backend-audit finding F5). The audit flagged three # *unmaintained* (not vulnerable, zero CVEs) transitive crates. None is # a direct Aivyx dependency — each is pulled deep under an upstream # crate we don't control — so there is no code change that removes them # until their parents update. Rather than let them sit as an unrecorded # "known issue," they are listed here with rationale: the gate stays # green on these three while still surfacing any *new* advisory. # Build the dependency graph with all features so the optional # local-LLM provider stacks (mistralrs → bm25/indicatif → fxhash / # number_prefix) are actually evaluated — otherwise those two # advisories are never encountered under default features and the # ignores below read as stale. [graph] all-features = true # License policy — Chapter Charter CR.1 (dependency license audit). # # Run: `cargo deny check licenses` # # Aivyx itself relicenses MIT → BUSL-1.1 (docs/LICENSING.md). For that to # be lawful, NO dependency may impose copyleft (GPL/LGPL-only/AGPL/MPL/ # SSPL/EPL/CDDL) on the combined work. This allow-list is therefore # permissive-only and deliberately omits every copyleft license: cargo-deny # rejects anything not listed, so a future copyleft dep fails the gate # loudly instead of silently poisoning the relicense. # # The list is the exact set of permissive SPDX ids present across the # all-features build graph (verified green at CR.1). Notes: # - "BSL-1.0" = the Boost Software License (permissive) — NOT the # Business Source License (BUSL-1.1) Aivyx itself adopts; unrelated. # - LGPL-2.1-or-later is intentionally ABSENT. It appears only as one # option of r-efi's "MIT OR Apache-2.0 OR LGPL-2.1-or-later"; because # MIT/Apache are allowed, the OR resolves to a permissive choice and # the copyleft option is never taken. Proof the gate works as intended. [licenses] version = 2 # Skip Aivyx's OWN workspace crates: they relicense to BUSL-1.1 (this gate's # whole purpose), so they must not be measured against the dependency # allow-list below. This is scoped to first-party crates marked publish = false # (see [workspace.package]); a THIRD-PARTY crate under BUSL/any copyleft still # fails loudly, which is the point. private = { ignore = true } allow = [ "MIT", "MIT-0", "Apache-2.0", "Apache-2.0 WITH LLVM-exception", "ISC", "BSD-2-Clause", "BSD-3-Clause", "Zlib", "BSL-1.0", "0BSD", "Unlicense", "WTFPL", "CC0-1.0", "Unicode-3.0", "Unicode-DFS-2016", "CDLA-Permissive-2.0", "NCSA", # MPL-2.0 is *file-level* (weak) copyleft: it never relicenses the larger # combined work — the only obligation is to share modifications to the # MPL-licensed files themselves, which we never touch (they are upstream # crates: the symphonia audio stack, the servo CSS stack pulled by Dioxus # — cssparser/selectors/dtoa-short — and option-ext via dirs). Fully # compatible with shipping Aivyx under BUSL-1.1. "MPL-2.0", ] # No per-crate license exceptions. The lone exception — GPL-3.0-only # `piper1-rs-sys` (Piper TTS → espeak-ng) — was eliminated in Chapter Timbre # (docs/TIMBRE.md TB.3/TB.4): Piper was replaced by the permissive Kokoro stack # (Kokoro-82M Apache-2.0 + `voice-g2p` MIT + `ort` Apache/MIT, espeak-free), so # there is **zero GPL anywhere in the dependency graph**, including the optional # `tts-kokoro` voice feature. `cargo deny check licenses` (all-features) is green # with no exceptions — any future copyleft dep now fails the gate loudly. [advisories] version = 2 # Treat unmaintained advisories as findings (so new ones surface), # except the three documented below. unmaintained = "all" yanked = "deny" ignore = [ # fxhash — RUSTSEC-2025-0057 (unmaintained). Pulled via # fxhash → bm25 → mistralrs-core → mistralrs → aivyx-llm # i.e. only when an in-process mistralrs local-LLM provider feature # is enabled. Not a direct dep; removable only when bm25/mistralrs # drop it. Not vulnerable. { id = "RUSTSEC-2025-0057", reason = "unmaintained, not vulnerable; transitive under mistralrs (bm25); awaiting upstream" }, # number_prefix — RUSTSEC-2025-0119 (unmaintained). Pulled via # number_prefix → indicatif 0.17 → hf-hub → mistralrs-core # Same mistralrs local-LLM stack. Not a direct dep. Not vulnerable. { id = "RUSTSEC-2025-0119", reason = "unmaintained, not vulnerable; transitive under mistralrs (indicatif→hf-hub); awaiting upstream" }, # paste — RUSTSEC-2024-0436 (unmaintained proc-macro). Pulled via # paste → frankenstein (+ macro_rules_attribute) → aivyx-telegram # paste → gemm → candle-core → candle-nn → mistralrs → aivyx-llm # (all-features graph: the local-model stack) # frankenstein is our Telegram Bot API wrapper; a 0.50 bump may drop # it, deferred to the Channel Activation Milestone (Telegram can't be # live-verified outside it). Not vulnerable. { id = "RUSTSEC-2024-0436", reason = "unmaintained, not vulnerable; transitive under frankenstein (aivyx-telegram) and under gemm/candle-core (mistralrs → aivyx-llm); revisit when both frankenstein and candle drop paste" }, # ── aivyx-desktop GTK3 webview stack ────────────────────────────── # The native desktop app (crates/aivyx-desktop) is a thin wry + tao # webview over the served Studio. On Linux that pulls webkit2gtk → the # gtk-rs GTK3 bindings, which upstream froze ("no longer maintained") # at glib 0.18: there is no glib >= 0.20 path while the webview is # GTK3-based, and the latest tao 0.35 / wry 0.55 still are (gtk 0.18.2 # pins glib ^0.18). All transitive and desktop-build-only — the # daemon / core / CLI never link them — and none is a vulnerability. # Revisit when the webview ecosystem moves to GTK4. The glib entry is # the GitHub Dependabot alert #6 (GHSA-wrw7-89jp-8q8g); same disposition. # (The gtk-rs "no longer maintained" advisories RUSTSEC-2024-0411..0420 # were withdrawn upstream on 2026-08-14 after the repository was # unarchived, so their ignore entries were removed 2026-10-28.) { id = "RUSTSEC-2024-0370", reason = "proc-macro-error unmaintained; transitive via glib-macros/gtk3-macros (aivyx-desktop GTK3); not vulnerable" }, # ttf-parser — RUSTSEC-2026-0192 (unmaintained). Pulled via # ttf-parser → pdf-extract → aivyx-dataread (data.pdf reader). # Arrived with the pdf-extract 0.9→0.12 upgrade that fixed the lopdf # stack-overflow DoS (RUSTSEC-2026-0187). Font parsing for PDF text # extraction; transitive, not a direct dep, and unmaintained (not # vulnerable). Removable only when pdf-extract drops/replaces it. { id = "RUSTSEC-2026-0192", reason = "ttf-parser unmaintained, not vulnerable; transitive under pdf-extract (data.pdf); arrived with the lopdf-DoS fix; awaiting upstream" }, # libsqlite3-sys — RUSTSEC-2026-0459 (CVE-2026-119375, accepted # 2026-11-11). The bundled SQLite before 3.54.0 can return stale # page-cache memory when a database is opened with a crafted `-wal` file # of a different page size. The fix (libsqlite3-sys 0.39 / rusqlite # 0.41) is unreachable here: matrix-sdk-sqlite 0.19.1 (aivyx-matrix's # crypto store, the latest release) requires rusqlite ^0.40.2, and only # one libsqlite3-sys may be linked (`links = "sqlite3"`). For the same # reason aivyx-kvcache is pinned to its `pa-sqlite-0.40` branch # (dd6adc8: 4ec85e4, rusqlite 0.40, plus the no-proxy fix); master # moved to 0.41. Exposure: pa opens only its own SQLite files (the # kvcache manifest, the Matrix crypto store) inside its private data # directory; planting a crafted -wal there already needs write access # to pa's state. Remove this entry, and pin aivyx-kvcache back to # master, when matrix-sdk-sqlite accepts rusqlite 0.41. { id = "RUSTSEC-2026-0459", reason = "bundled SQLite -wal memory exposure; fix blocked by matrix-sdk-sqlite 0.19.1 (rusqlite ^0.40.2); pa opens only its own DB files in its data dir; revisit on the next matrix-sdk release" }, # NOTE: glib RUSTSEC-2024-0429 (GHSA-wrw7-89jp-8q8g, GitHub Dependabot # alert #6) — a `glib::VariantStrIter` Iterator/DoubleEndedIterator # *unsoundness*, same aivyx-desktop GTK3 root cause (glib 0.18, patched # only in 0.20 which is unreachable via GTK3; not exercised by the thin # webview shell). Not listed as an `ignore` entry: cargo-deny 0.20 does # check `unsound` advisories, but its default scope is the workspace's # own direct dependencies, and glib is only transitive (via # wry/tao/tray-icon), so it is not flagged (an entry would be a # perpetual "unused ignore"; verified 2026-10-28). Recorded here as the # accepted disposition; mirror it by dismissing Dependabot #6 as # "tolerable risk". If a future cargo-deny flags it, add an entry with # this disposition. # ── 2026-10-28 additions (Chapter H) ───────────────────────────── # zip — RUSTSEC-2026-0367/0368/0369 (ZipArchive::extract / ZipStreamReader # ::extract). The workspace's own zip uses (aivyx-voice Kokoro npz, # aivyx-dataread via calamine/rust_xlsxwriter) were moved to zip 9 on this # date, which is fixed. One copy remains: zip 7.2.0 under candle-core # (mistralrs-core local-LLM stack), which only calls ZipArchive::new / # by_name to read .npz/.pth weights in memory and never calls extract. { id = "RUSTSEC-2026-0367", reason = "zip 7.2.0 via candle-core (mistralrs, aivyx-llm local provider); the advisory is about ZipArchive::extract, which candle never calls (it reads npz/pth archives in memory); fixed only in zip 9, revisit when candle-core/mistralrs move" }, { id = "RUSTSEC-2026-0368", reason = "zip 7.2.0 via candle-core (mistralrs, aivyx-llm local provider); the advisory is about ZipArchive::extract, which candle never calls (it reads npz/pth archives in memory); fixed only in zip 9, revisit when candle-core/mistralrs move" }, { id = "RUSTSEC-2026-0369", reason = "zip 7.2.0 via candle-core (mistralrs, aivyx-llm local provider); the advisory is about ZipArchive::extract, which candle never calls (it reads npz/pth archives in memory); fixed only in zip 9, revisit when candle-core/mistralrs move" }, { id = "RUSTSEC-2026-0429", reason = "zip 7.2.0 via candle-core (mistralrs, aivyx-llm local provider); the advisory is about ZipArchive::extract sizing a symlink-target buffer, and candle never calls extract (it reads npz/pth archives in memory); fixed only in zip 9, revisit when candle-core/mistralrs move" }, # anymap2 — RUSTSEC-2026-0319 (unmaintained). Pulled via # anymap2 → matrix-sdk 0.19.1 → aivyx-matrix. Not a direct dep; # matrix-sdk 0.19.1 is the latest release. Not vulnerable. { id = "RUSTSEC-2026-0319", reason = "anymap2 unmaintained, not vulnerable; transitive under matrix-sdk 0.19.1 (aivyx-matrix), the latest release; revisit when matrix-sdk drops it" }, # pin-utils — RUSTSEC-2026-0441 (unmaintained). Pulled via # pin-utils → async-imap 0.11.3 → aivyx-proton (Proton Bridge preview). # No fixed version; async-imap 0.12 is an API change. Not vulnerable. { id = "RUSTSEC-2026-0441", reason = "pin-utils unmaintained, not vulnerable; transitive under async-imap 0.11.3 (aivyx-proton); revisit with async-imap 0.12" }, # zbus 4.4.0 stack — RUSTSEC-2026-0370 (zvariant), 0371 (zbus_names), # 0372 (zvariant_derive), all unmaintained. Pulled via # zbus 4.4.0 → keyring 3.6.3 / secret-service 4.0.0 → aivyx-channel # (Linux secret-service keyring). keyring 4's default Linux store still # uses zbus 5, so moving to keyring 4 is not the exit; the exits are a # zbus 6 based secret-service, or keyring's dbus/libdbus store. Not # vulnerable. { id = "RUSTSEC-2026-0370", reason = "zvariant unmaintained, not vulnerable; transitive under zbus 4.4.0 via keyring 3 (aivyx-channel); revisit when secret-service moves to zbus 6 or keyring uses its dbus (libdbus) store" }, { id = "RUSTSEC-2026-0371", reason = "zbus_names unmaintained, not vulnerable; transitive under zbus 4.4.0 via keyring 3 (aivyx-channel); revisit when secret-service moves to zbus 6 or keyring uses its dbus (libdbus) store" }, { id = "RUSTSEC-2026-0372", reason = "zvariant_derive unmaintained, not vulnerable; transitive under zbus 4.4.0 via keyring 3 (aivyx-channel); revisit when secret-service moves to zbus 6 or keyring uses its dbus (libdbus) store" }, ]