From 465c7ba2b08d0cb3a11b408525d29de7d386882c Mon Sep 17 00:00:00 2001 From: Mollusk Date: Thu, 18 Jun 2026 15:46:52 -0400 Subject: [PATCH] Add cargo-deny supply-chain policy (deny.toml) Supersede bare cargo-audit with an enforceable four-part policy, validated against the current tree with cargo-deny 0.19.9 (advisories/bans/licenses/ sources all pass): - advisories: deny vulnerabilities + yanked; ignore the two *unmaintained* warnings (paste RUSTSEC-2024-0436, audiopus_sys RUSTSEC-2026-0150) with rationale. Both are transitive and pinned via Cargo.lock, so a future malicious release can't reach us until a deliberate cargo update. - sources: trust only crates.io; deny unknown registries and git sources (core anti-hijack control). - bans: deny wildcard version reqs; warn on duplicate versions. - licenses: permissive allow-list covering the current graph. Mark peerspeak publish = false (it's an application, not a published library): blocks accidental cargo publish and lets [licenses.private] skip the missing-license check. Co-Authored-By: Claude Opus 4.8 --- Cargo.toml | 3 ++ deny.toml | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 deny.toml diff --git a/Cargo.toml b/Cargo.toml index 739b7fe..4cbfedc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,9 @@ name = "peerspeak" version = "0.2.0" edition = "2024" +# Application crate, not a crates.io library — refuse `cargo publish` and let +# cargo-deny's [licenses.private] skip the missing-license check. +publish = false [lib] name = "peerspeak" diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..1aaef9f --- /dev/null +++ b/deny.toml @@ -0,0 +1,88 @@ +# cargo-deny policy for peerspeak +# +# Supersedes a bare `cargo audit` run. Enforce with: +# cargo install cargo-deny --locked +# cargo deny check +# +# In CI, run `cargo deny check` on a locked tree so the pinned, vetted +# versions in Cargo.lock are what actually get audited. + +# --------------------------------------------------------------------------- +# Advisories: RustSec database. Vulnerabilities and yanked crates are denied +# by default. The two `ignore` entries below are *unmaintained* warnings only +# (no known exploit); they are deep transitive deps we cannot remove. Pinning +# them via Cargo.lock is our real protection — a future malicious release does +# not reach us until we deliberately `cargo update`, so each update is a review +# checkpoint. Revisit these if either advisory is upgraded to a vulnerability. +# --------------------------------------------------------------------------- +[advisories] +ignore = [ + # paste: unmaintained, compile-time proc-macro only (zero runtime surface), + # transitive via iroh/netdev/netlink and rav1e/image/iced. Maintained fork + # `pastey` is already in the tree; stragglers will follow upstream. + "RUSTSEC-2024-0436", + # audiopus_sys: unmaintained FFI bindings to the stable libopus C library, + # pulled in via our direct `opus 0.3.1` dep. No drop-in replacement. + "RUSTSEC-2026-0150", +] + +# --------------------------------------------------------------------------- +# Bans: shape of the dependency graph. +# --------------------------------------------------------------------------- +[bans] +# Multiple versions of the same crate bloat the build; warn rather than fail +# since transitive graphs (iroh, iced) routinely carry duplicates we can't fix. +multiple-versions = "warn" +# Wildcard ("*") version requirements are a supply-chain footgun: they accept +# any future release, defeating the lockfile-as-review-checkpoint model. +wildcards = "deny" +# ...but our own intra-repo path deps may use "*"; don't penalize those. +allow-wildcard-paths = true + +# Crates that may never appear in the graph. Add a maintained replacement's +# predecessor here once you've migrated off it, to prevent regressions. +deny = [] + +# --------------------------------------------------------------------------- +# Sources: where crates are allowed to come from. This is the core anti-hijack +# control — only the official crates.io registry is trusted; arbitrary git +# sources (a common vector for slipping in unaudited code) are rejected. +# --------------------------------------------------------------------------- +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# allow-git = [] # add a specific, pinned git repo here only if ever needed + +# --------------------------------------------------------------------------- +# Licenses: permissive set covering the current graph. If `cargo deny check` +# reports an unmatched license, vet it and add the SPDX id here (or add a +# per-crate entry under [licenses.exceptions]) rather than widening blindly. +# --------------------------------------------------------------------------- +[licenses] +allow = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Zlib", + "MPL-2.0", + "Unicode-3.0", + "Unicode-DFS-2016", + "CC0-1.0", + "0BSD", + "Unlicense", + "BSL-1.0", + "NCSA", # University of Illinois/NCSA — BSD-like permissive + "CDLA-Permissive-2.0", # Community Data License Agreement, permissive +] +confidence-threshold = 0.8 +exceptions = [] + +# peerspeak itself has no `license` field and is not published, so skip the +# "unlicensed" check for our own (private) crate. Add a license to Cargo.toml +# if/when this is ever published. +[licenses.private] +ignore = true