From fdfce69358d816e4aebe8432178302e59a6ed85c Mon Sep 17 00:00:00 2001 From: Linwei Shang Date: Wed, 5 Aug 2026 16:00:44 -0400 Subject: [PATCH 1/2] ci: replace cargo-audit with cargo-deny advisories The Audit workflow had been failing on RUSTSEC-2026-0235 (rkyv), which cargo-audit reads out of Cargo.lock even though no enabled feature activates the crate -- `cargo tree -i rkyv` is empty. cargo-deny resolves the actual feature graph, so it never sees rkyv; 87 of 770 lockfile crates are likewise excluded. Advisories move into the cargo-deny job, restricted to vulnerabilities. Informational advisories (unmaintained, unsound, notice) are transitive crates we do not pick, usually with no patched version, and GHSA omits them so Dependabot never raises them either. That retires the hand-maintained suppression list in .cargo/audit.toml, which had gone stale. Dependabot stays the primary alerting and auto-fix channel but cannot replace this check: 33% of 2026 RustSec vulnerabilities have no GHSA counterpart, including RUSTSEC-2026-0188, the wasmtime-wasi FilePerms bypass fixed here in 5dc868f7 and still absent from GHSA six weeks on. deny.toml is refreshed following dfinity/candid#757: per-section rationale, and the entries inherited from the deprecated sdk repo that no longer hold are gone -- allow-git for agent-rs, since the graph contains no git dependency at all, and the unused OpenSSL and Unicode-DFS-2016 licenses. The workflow is renamed off "license check" as it no longer only checks licenses, drops the apt provisioning cargo-deny has no use for, and runs weekly rather than daily: with 2-17 PRs merged per week and pull_request left unfiltered, the cron only has to cover quiet weeks. Co-Authored-By: Claude Opus 5 (1M context) --- .cargo/audit.toml | 11 ----- .github/workflows/audit.yml | 44 -------------------- .github/workflows/deny.yml | 38 ----------------- .github/workflows/dependencies.yml | 31 ++++++++++++++ deny.toml | 67 +++++++++++++++++++++--------- 5 files changed, 78 insertions(+), 113 deletions(-) delete mode 100644 .cargo/audit.toml delete mode 100644 .github/workflows/audit.yml delete mode 100644 .github/workflows/deny.yml create mode 100644 .github/workflows/dependencies.yml diff --git a/.cargo/audit.toml b/.cargo/audit.toml deleted file mode 100644 index 28c770d98..000000000 --- a/.cargo/audit.toml +++ /dev/null @@ -1,11 +0,0 @@ -[advisories] -ignore = [ - "RUSTSEC-2025-0140", # gix-date UTF-8 contract issue dependency of cargo-generate - "RUSTSEC-2026-0235", # rkyv is an unused optional dependency of rust_decimal which has not been updated yet - - # Unmaintained crates (transitive dependencies) - "RUSTSEC-2021-0127", # serde_cbor - dependency of ic-agent/ic-transport-types - "RUSTSEC-2024-0384", # instant - dependency of backoff, cached, parking_lot, rhai - "RUSTSEC-2024-0436", # paste - dependency of candid, cargo-generate - "RUSTSEC-2025-0012", # backoff - dependency of ic-agent -] diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml deleted file mode 100644 index 5070eafe7..000000000 --- a/.github/workflows/audit.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Audit - -on: - push: - branches: - - main - paths-ignore: - - "**.md" - - "docs/**" - pull_request: - paths-ignore: - - "**.md" - - "docs/**" - schedule: - # * is a special character in YAML so you have to quote this string - - cron: "0 14 * * *" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - # When getting Rust dependencies, retry on network error: - CARGO_NET_RETRY: 10 - # Use the local .curlrc - CURL_HOME: . - # Disable DFX telemetry - DFX_TELEMETRY: "off" - # Use the stable toolchain for the audit - RUSTUP_TOOLCHAIN: stable - -jobs: - test: - name: audit:required - runs-on: ubuntu-latest - permissions: - contents: read - issues: write - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup image (Linux) - run: ./.github/scripts/provision-linux-build.sh - - uses: actions-rust-lang/audit@72c09e02f132669d52284a3323acdb503cfc1a24 # v1.2.7 diff --git a/.github/workflows/deny.yml b/.github/workflows/deny.yml deleted file mode 100644 index cfd4b46a3..000000000 --- a/.github/workflows/deny.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: License Check - -on: - push: - branches: - - master - paths-ignore: - - "**.md" - - "docs/**" - pull_request: - paths-ignore: - - "**.md" - - "docs/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - # When getting Rust dependencies, retry on network error: - CARGO_NET_RETRY: 10 - # Use the local .curlrc - CURL_HOME: . - # Disable DFX telemetry - DFX_TELEMETRY: "off" - -jobs: - cargo-deny: - name: license-check:required - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Setup image (Linux) - run: ./.github/scripts/provision-linux-build.sh - - run: rm rust-toolchain.toml - - uses: EmbarkStudios/cargo-deny-action@3fd3802e88374d3fe9159b834c7714ec57d6c979 # v2.0.15 - with: - command: check bans licenses sources # skip advisories, which are handled by audit.yml diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml new file mode 100644 index 000000000..2f4c1f6bc --- /dev/null +++ b/.github/workflows/dependencies.yml @@ -0,0 +1,31 @@ +name: Dependencies + +on: + # Unfiltered: a run skipped by a path filter reports no conclusion, which would + # leave `dependencies:required` pending forever on every unrelated PR. + pull_request: + # Backstop for weeks with no PRs. Advisories are the one finding here that can + # appear with no change on our side, so re-check against the RustSec database. + schedule: + - cron: "0 14 * * 1" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # When getting Rust dependencies, retry on network error: + CARGO_NET_RETRY: 10 + +jobs: + cargo-deny: + name: dependencies:required + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + # rust-toolchain.toml is left in place so the graph is resolved by the same + # cargo that builds our releases. It costs ~30s of toolchain install, and + # buys us not depending on the action image's Rust being new enough. + - uses: EmbarkStudios/cargo-deny-action@3fd3802e88374d3fe9159b834c7714ec57d6c979 # v2.0.15 + with: + command: check advisories bans licenses sources diff --git a/deny.toml b/deny.toml index 553ff39b6..c455f6ad6 100644 --- a/deny.toml +++ b/deny.toml @@ -1,26 +1,53 @@ -# adapted from https://github.com/dfinity-lab/common/blob/master/pkgs/overlays/packages/cargo-deny/buildtime.toml -# for context, see https://github.com/dfinity-lab/common/blob/master/pkgs/overlays/packages/cargo-deny/runtime.toml -# we allow more licenses in the build-time check. all rust dependencies are statically linked, -# so copyleft licenses like MPL which allow static linking are A-OK +# Dependency policy for icp-cli, enforced by the Dependencies workflow. icp-cli +# ships a linked binary, so these rules cover what we may distribute rather than +# obligations passed to downstream crates (cf. dfinity/candid). + +[graph] +# Dev-only deps never reach the released binary. Explicit so a changed default +# cannot silently widen the graph. +exclude-dev = true + +[advisories] +# Vulnerabilities are always denied. Informational advisories are transitive +# crates we do not pick, usually with no patched version, and GHSA omits them so +# Dependabot never raises them either. Replaces the stale hand-maintained ignore +# list in .cargo/audit.toml. +unmaintained = "none" +# Not a vulnerability, and usually clears on the next `cargo update`. +yanked = "warn" + [licenses] +# Binary distribution, so: attribution-only terms, plus MPL-2.0, whose copyleft +# is file-scoped and we modify none of those files. Strong copyleft would reach +# the whole linked binary. Unlisted licenses are denied. +# +# ittapi (GPL-2.0-only) and r-efi (LGPL-2.1-or-later) are dual-licensed and +# satisfied from an entry below. allow = [ - "Apache-2.0", - "Apache-2.0 WITH LLVM-exception", - "BlueOak-1.0.0", - "BSD-2-Clause", - "BSD-3-Clause", - "CC0-1.0", - "CDLA-Permissive-2.0", - "ISC", - "MIT", - "MPL-2.0", - "Zlib", - "Unicode-DFS-2016", - "Unicode-3.0", - "OpenSSL", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "BlueOak-1.0.0", + "CC0-1.0", + "CDLA-Permissive-2.0", + "ISC", + "MIT", + "MPL-2.0", + "Unicode-3.0", + "Zlib", ] -unused-allowed-license = "allow" +# OpenSSL and Unicode-DFS-2016 sat here unused for years; warn on the next drift. +unused-allowed-license = "warn" + +[bans] +# ~60 shared crates differ across cargo-generate, wasmtime, ic-agent and reqwest +# pins we do not control. +multiple-versions = "allow" [sources] -allow-git = ["https://github.com/dfinity/agent-rs.git"] +# Everything resolves from crates.io, and a git revision is mutable enough to +# make a tagged release non-reproducible. cargo-deny only warns by default. +unknown-registry = "deny" +unknown-git = "deny" From 0c9579fac3872f78a9f614a6ab864b03f918fe23 Mon Sep 17 00:00:00 2001 From: Linwei Shang Date: Wed, 5 Aug 2026 16:02:18 -0400 Subject: [PATCH 2/2] ci: format deny.toml with taplo The array indentation followed candid's four spaces; taplo.toml wants two. Co-Authored-By: Claude Opus 5 (1M context) --- deny.toml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deny.toml b/deny.toml index c455f6ad6..cd90712d0 100644 --- a/deny.toml +++ b/deny.toml @@ -24,18 +24,18 @@ yanked = "warn" # ittapi (GPL-2.0-only) and r-efi (LGPL-2.1-or-later) are dual-licensed and # satisfied from an entry below. allow = [ - "Apache-2.0", - "Apache-2.0 WITH LLVM-exception", - "BSD-2-Clause", - "BSD-3-Clause", - "BlueOak-1.0.0", - "CC0-1.0", - "CDLA-Permissive-2.0", - "ISC", - "MIT", - "MPL-2.0", - "Unicode-3.0", - "Zlib", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "BlueOak-1.0.0", + "CC0-1.0", + "CDLA-Permissive-2.0", + "ISC", + "MIT", + "MPL-2.0", + "Unicode-3.0", + "Zlib", ] # OpenSSL and Unicode-DFS-2016 sat here unused for years; warn on the next drift.