# cargo-deny configuration for the JellyTau backend. # # TRACES: | DR-216 # # Run locally with: cd src-tauri && cargo deny check # CI runs the same command in the `security` job of # .gitea/workflows/build-and-test.yml. cargo-deny is baked into the builder # image (Dockerfile.builder) -- the advisory database it fetches at run time is # *data*, not a toolchain, so it does not conflict with the "CI installs no # system tools" rule. # # Four checks run: advisories (known vulnerabilities), licenses (what we are # allowed to ship), bans (duplicate/undesired crates) and sources (where code # may come from). # --------------------------------------------------------------------------- # Graph scope # # Only the targets JellyTau actually ships. This is not a performance tweak -- # it changes which advisories are *real*. Without it the graph includes Apple # targets, which drag in `plist` -> `quick-xml`, and two quick-xml DoS # advisories (RUSTSEC-2026-0194/0195) get reported against a crate that is not # compiled into anything we release. Ignoring them by ID would have been the # wrong fix: it silences the finding everywhere, including on a target where it # would matter. Scoping the graph makes the finding correctly absent instead. # # Add a target here the day we ship it, and expect new findings with it. [graph] targets = [ "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc", "aarch64-linux-android", "armv7-linux-androideabi", "x86_64-linux-android", ] all-features = true [advisories] # Vulnerabilities and unsoundness are hard errors -- there is deliberately no # switch here turning them into warnings. Everything below is an explicit, # justified exception with a named ID; a new advisory fails the build until # somebody decides what to do about it. # # Yanked crates in the lockfile are an error too: a yank usually means the # author withdrew that exact version for a reason. yanked = "deny" ignore = [ # --------------------------------------------------------------------- # GTK3 bindings: unmaintained, and not ours to replace. # # Tauri v2's Linux backend is WebKitGTK, which is GTK3. The gtk-rs project # has stopped maintaining its GTK3 bindings in favour of GTK4, but Tauri # cannot move until WebKitGTK does. These arrive through # tauri -> tauri-runtime-wry -> wry -> gtk, with no version of any of them # that avoids it ("No safe upgrade is available", per cargo-deny). # # Unmaintained != vulnerable: no advisory here describes an exploitable # defect. Revisit when Tauri ships a GTK4/WebKitGTK-6 backend. { id = "RUSTSEC-2024-0411", reason = "gdkwayland-sys: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0412", reason = "gdk: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0413", reason = "atk: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0414", reason = "gdkx11-sys: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0415", reason = "gtk: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0416", reason = "atk-sys: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0417", reason = "gdkx11: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0418", reason = "gdk-sys: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0419", reason = "gtk3-macros: GTK3 binding, pulled in by Tauri's Linux backend" }, { id = "RUSTSEC-2024-0420", reason = "gtk-sys: GTK3 binding, pulled in by Tauri's Linux backend" }, # --------------------------------------------------------------------- # Unmaintained transitive build-time crates. All are proc-macro or # lookup-table dependencies of Tauri's own toolchain; none has a safe # upgrade and none is a vulnerability. { id = "RUSTSEC-2024-0370", reason = "proc-macro-error: unmaintained proc-macro helper, transitive" }, { id = "RUSTSEC-2024-0436", reason = "paste: unmaintained macro helper, transitive" }, { id = "RUSTSEC-2025-0057", reason = "fxhash: unmaintained hasher, transitive" }, # unic-* reach us via urlpattern -> tauri-utils. Unicode table crates, # superseded upstream but with no drop-in replacement at this depth. { id = "RUSTSEC-2025-0075", reason = "unic-char-range: unmaintained, via urlpattern -> tauri-utils" }, { id = "RUSTSEC-2025-0080", reason = "unic-common: unmaintained, via urlpattern -> tauri-utils" }, { id = "RUSTSEC-2025-0081", reason = "unic-char-property: unmaintained, via urlpattern -> tauri-utils" }, { id = "RUSTSEC-2025-0098", reason = "unic-ucd-version: unmaintained, via urlpattern -> tauri-utils" }, { id = "RUSTSEC-2025-0100", reason = "unic-ucd-ident: unmaintained, via urlpattern -> tauri-utils" }, ] # --------------------------------------------------------------------------- # Licenses # # JellyTau ships as MIT (see ../LICENSE) in deb/rpm/AppImage/NSIS/APK bundles, # so every crate compiled into those has to be redistributable under terms # compatible with that. The list is an allow-list on purpose: a new crate with # an unlisted licence fails the build and gets a decision, rather than being # shipped because nobody looked. [licenses] # A crate offering a choice ("MIT OR Apache-2.0") is satisfied by any allowed # arm. 0.8 means we accept a licence-file match at >=80% textual confidence. confidence-threshold = 0.8 allow = [ # Permissive, no redistribution conditions beyond attribution. "MIT", "MIT-0", "Apache-2.0", "Apache-2.0 WITH LLVM-exception", "BSD-2-Clause", "BSD-3-Clause", "ISC", "Zlib", "0BSD", "CC0-1.0", "Unlicense", "BSL-1.0", # Unicode data tables (the icu_* family). Permissive, attribution only. "Unicode-3.0", # webpki-roots: the Mozilla CA bundle, published as data under CDLA. "CDLA-Permissive-2.0", # MPL-2.0 -- weak, *file-level* copyleft (cssparser, selectors, dtoa-short, # option-ext). The obligation attaches to modified MPL files, not to the # program that links them, so shipping them unmodified inside an MIT # application is fine. If we ever patch one of these crates, that patch must # be published. "MPL-2.0", # LGPL-2.1 -- `libmpv` and `libmpv-sys` only, and this one is deliberate. # # These are bindings to libmpv, which is itself LGPL-2.1+; the binding # crates inherit the licence. LGPL permits use from a differently-licensed # application provided the user can substitute their own build of the # library, which dynamic linking satisfies -- libmpv-sys links the *system* # shared object (the builder image installs libmpv-dev; the deb/rpm declare # a runtime dependency) rather than statically embedding it. # # 🔴 Two obligations follow, and they are ours, not cargo-deny's: # - keep the linkage dynamic (do not switch libmpv-sys to a vendored # static build without revisiting this), # - ship libmpv's licence text with any bundle that carries the .so, # which currently means the AppImage. "LGPL-2.1", ] # Crates whose licence field is missing or unparseable get a per-crate # clarification here rather than a blanket relaxation. Empty today. exceptions = [] [bans] # Duplicate versions are noise, not danger: a Tauri-sized graph legitimately # carries several `windows-sys` and `bitflags` majors because its dependencies # upgrade at different rates. Warn so the count stays visible; do not fail. multiple-versions = "warn" # The only wildcard in the graph is the `libmpv` git dependency: a git dep # carries no semver requirement, so cargo-deny counts it as `*` no matter how it # is pinned. It is pinned by `rev` in Cargo.toml and by hash in Cargo.lock, and # `[sources].allow-git` below is the check that actually constrains it -- so # "deny" here would fail the build forever over something already controlled # twice. Warn, so a *second* wildcard still shows up. wildcards = "warn" # `cargo build` order for equal-priority features; keeps the check deterministic. highlight = "all" deny = [] skip = [] [sources] # Anything not from crates.io needs to be named here. This is the check that # would notice a dependency being repointed at somebody's fork. unknown-registry = "deny" unknown-git = "deny" allow-registry = ["https://github.com/rust-lang/crates.io-index"] # The one git dependency. Cargo.toml pins it by branch, not by revision, which # is worth knowing: the `master` it resolves to is whatever the lockfile has # recorded, and `cargo update` will move it. It exists because the crates.io # release of libmpv predates the MPV versions we support. allow-git = ["https://github.com/ParadoxSpiral/libmpv-rs.git"]