# cargo-deny configuration. Run with `cargo deny check`. # # Every section below is a decision, not the tool's default. See the # workspace `Cargo.toml`'s own dependency comments (the jacquard pin, the # `ring` vs `aws-lc-rs` choice) for the standard this file is trying to # match: name the reason, not just the rule. # didbot ships two real artifacts: the server binary (`didbot-dev`, built by # the Dockerfile from `rust:1.90-slim-bookworm`, i.e. glibc x86_64 Linux) and # `didbot-site-anim`, compiled to `wasm32-unknown-unknown` for the did.bot # site (see crates/didbot-site-anim/Cargo.toml and # site/scripts/build-wasm.sh). Restricting the graph to these two targets, # rather than every platform `Cargo.lock` happens to resolve entries for, # is what keeps this file honest: `r-efi` (LGPL-2.1-or-later, pulled in only # for UEFI/wasm32-wasi targets via getrandom's wasi backend) and a long tail # of windows-only and jni/android-only crates never build for either binary # this project actually produces, and listing them as license or ban # exceptions would be recording a decision nobody needs to make. [graph] targets = [ "x86_64-unknown-linux-gnu", "wasm32-unknown-unknown", ] # This project has no other registry and no reason to trust one; `cargo # update` from a mirror or a `[patch]` pointed at a fork would be a supply # chain change worth catching on its own, not something this audit should # pre-approve. all-features = false no-default-features = false # advisories: RUSTSEC's database of known vulnerabilities, unmaintained # crates, and yanked releases against the exact versions in Cargo.lock. [advisories] db-path = "~/.cargo/advisory-db" db-urls = ["https://github.com/rustsec/advisory-db"] # Every id below is an explicit decision, each with the exposure it means # for *this* project — not a blanket ignore list. `cargo deny check # advisories` fails the moment a new one appears that isn't named here, # which is the point: nothing is silently allowed. ignore = [ # RUSTSEC-2023-0071 -- Marvin Attack: `rsa` 0.9.10 has no non-constant- # time-free release, so no upgrade fixes this. Reachable via # didbot-attest (AWS instance-identity PKCS#7 verification, # crates/didbot-attest/src/aws/pkcs7.rs) and via jose-jwk (pulled in by # jacquard-oauth for JWK parsing). # # Checked both call sites: didbot-attest's production code only calls # `RsaPublicKey::verify` (pkcs7.rs); the only `RsaPrivateKey`/`SigningKey` # use in that crate is under `#[cfg(test)]` fixture code that signs # fixtures for the verifier's own tests, never runs in a deployed # instance. jose-jwk exists to parse the *server's* published JWK set for # an OAuth *client* (didbot-claim authenticates as an account; it does # not issue tokens), so it has no reason to hold or use an RSA private # key either. The Marvin Attack is a timing side-channel in private-key # operations observable over a network; a verify-only, public-key-only # user of this crate does not expose it. Re-check this reasoning if # either crate gains a private-key code path. # # Lifts once `rsa` publishes a constant-time-safe release -- the # advisory's own `patched` list is empty today, so track # https://github.com/RustCrypto/RSA/issues/19 -- and didbot-attest's # `rsa = "0.9.8"` (crates/didbot-attest/Cargo.toml) moves to it. "RUSTSEC-2023-0071", ] # licenses: which SPDX terms this dependency tree may carry, and why. # # This project's own `license = "MIT"` (workspace Cargo.toml) says what # didbot's *own* code is offered under. The dependency tree is judged # against a stricter question: didbot ships as a server binary holding # operator credentials and signing keys (see CLAUDE.md's principles), so # strong copyleft (GPL/AGPL) has no exception here -- there is no # "build-time tool" carve-out available to a statically linked, source- # distributed server the way there would be for, say, a CI script. Weak/ # file-level copyleft (MPL-2.0) and all the standard permissive terms are # accepted; MPL's obligation attaches to the licensed files themselves, not # to a program that links against them, which is a materially different # question from GPL. [licenses] allow = [ "MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "Unicode-3.0", "Unlicense", "Zlib", "0BSD", "MIT-0", # Boost Software License. Permissive; used by `ryu` (dtolnay, # dual-licensed Apache-2.0/BSL-1.0 -- cargo-deny picked the BSL-1.0 arm). "BSL-1.0", # Mozilla's Common Data Language Agreement, applied to `webpki-roots`' # embedded Mozilla CA certificate bundle. It's a data-license on a list # of root certificates, not a code copyleft term. "CDLA-Permissive-2.0", # Weak/file-level copyleft -- see the comment above this table. Carried # by the `jacquard-*` crates, this project's atproto client/identity # library. "MPL-2.0", # Apache-2.0 with the LLVM exception, which only *relaxes* Apache's # attribution terms for binary redistribution. Carried by # `ar_archive_writer`, a build-time dependency of `psm`, which is how # `stacker` grows the stack for `cedar-policy-core`'s recursive parser # and evaluator (crates/didbot-policy-cedar). "Apache-2.0 WITH LLVM-exception", ] confidence-threshold = 0.8 exceptions = [] [[licenses.clarify]] # ring's license field isn't SPDX-expressible (a mix of its own ISC-style # grant, an OpenSSL-derived BSD/ISC blend, and public-domain code); this is # the standard clarification the crate's own maintainers publish, matched # against the LICENSE file's hash so it stops applying the moment the text # changes underneath it. crate = "ring" expression = "MIT AND ISC AND OpenSSL" license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] [licenses.private] ignore = false # bans: duplicate versions of the same crate, and crates this project has # decided never belong in its graph. [bans] multiple-versions = "deny" wildcards = "deny" # A workspace member depending on another only by version (no `path`) would # resolve from crates.io instead of the sibling crate actually being edited # -- exactly the kind of thing this project's `publish = false` workspace # should never do by accident. workspace-dependencies = { duplicates = "deny", include-path-dependencies = true } # Every skip below is a duplicate `cargo deny check bans` found under the # real build targets (see `[graph.targets]`), each with why it's tolerated # rather than fixed here. None of these are vendoring or pinning decisions; # they're upstream crates' own choices about which major version of a # dependency to require, several layers below this workspace's control. skip = [ # rand 0.8 / 0.9 / 0.10 in one graph, and it matters here specifically: # this project generates OAuth PKCE verifiers and DPoP material through # jacquard-oauth, which is pinned to rand 0.8 upstream (see the # workspace Cargo.toml's jacquard pin comment -- unpinning it is a # dependency bump of its own, not this audit's job). rand 0.8.7 carries # no open RUSTSEC advisory as of this audit; the duplication is # ecosystem churn, not a broken RNG. rand 0.9 is this workspace's own # explicit pin (`rand = "0.9"` in Cargo.toml, used directly). Two copies # of a *keyed*-CSPRNG-adjacent crate would be a real hazard if they # disagreed about the underlying `getrandom` call; they don't -- each # rand major pulls its own getrandom major (below), and every one of # those still reads from the OS's CSPRNG, not from each other. { name = "rand", version = "0.8" }, { name = "rand_core", version = "0.6" }, { name = "rand_chacha", version = "0.3" }, { name = "getrandom", version = "0.2" }, { name = "getrandom", version = "0.4" }, # digest / block-buffer / crypto-common / cpufeatures, one version each # newer than the rest of the graph: all four exist solely because # argon2 0.6's internal blake2 use (RustCrypto's own KDF construction, # crates/didbot-pds's password hashing) has moved ahead of the line # every other RustCrypto crate in this graph (sha2, hmac, k256, p256, # ed25519-dalek, ...) still uses. Not user-reachable: nothing in this # workspace calls `digest`, `block-buffer` or `cpufeatures` directly, # and argon2 does not expose blake2's trait implementations through its # own API. Two *incompatible trait* copies would be a real bug source if # this workspace's own code mixed them; it doesn't. { name = "digest", version = "0.11" }, { name = "block-buffer", version = "0.12" }, { name = "crypto-common", version = "0.2" }, { name = "cpufeatures", version = "0.3" }, # base64 0.22 (reqwest/axum's choice) vs 0.23 (rcgen/pem's choice). # Encoding only -- no key material handling of its own, unlike # the entries above -- and the workspace's own security-relevant base64 # use (PKCE's S256 challenge, see the Cargo.toml comment on the `base64` # dependency) goes through the 0.22 line via reqwest. { name = "base64", version = "0.23" }, # thiserror 1 vs 2: x509-parser 0.16 (didbot-tls's certificate parsing) # hasn't moved to thiserror 2 yet; this workspace's own crates all use # the 2.x line (`thiserror.workspace = true`). Error-derive macro only, # no runtime behaviour difference that reaches across the boundary. { name = "thiserror", version = "1" }, { name = "thiserror-impl", version = "1" }, # Pure build-time / proc-macro or data-structure churn: no runtime # security surface, and each pair is two crates in the graph disagreeing # about a dependency's major version rather than anything this project # chose. hashbrown has three because indexmap, ipld-core-adjacent code, # and icu (unicode-segmentation's tables) each pin a different one. { name = "syn", version = "3" }, { name = "winnow", version = "1" }, { name = "hashbrown", version = "0.14" }, { name = "hashbrown", version = "0.15" }, { name = "spin", version = "0.10" }, # Two more of the same shape, both under `cedar-policy` (the policy # engine in crates/didbot-policy-cedar): `lalrpop`'s build-time parser # generator is one `itertools` major behind `cedar-policy-core`, and # `miette`'s error rendering is one `unicode-width` major behind # `pretty`'s. Neither reaches a request: one runs at build time, the # other measures text for error messages. { name = "itertools", version = "0.14" }, { name = "unicode-width", version = "0.1" }, ] # Nothing is on this list yet, but the section exists so the next crate this # project decides against has one line to add rather than a debate re-run # from scratch. Candidates that came up while writing this file and were # *not* added: `openssl`/`openssl-sys` (this workspace deliberately stays on # rustls+ring end to end, see the workspace Cargo.toml's `instant-acme` # comment) would be worth forbidding outright if it ever appears, but # forbidding a crate that isn't in the graph today is a rule with nothing to # test it against. deny = [] # sources: where a dependency is allowed to come from. [sources] unknown-registry = "deny" unknown-git = "deny" allow-registry = ["https://github.com/rust-lang/crates.io-index"] allow-git = []