Skip to content

Commit 2172d60

Browse files
feat(ci): add cargo audit + cargo deny to contracts CI pipeline (#371)
* feat(ci): add cargo audit + cargo deny to contracts CI pipeline Implements issue #136 by adding a dedicated contracts-audit job that runs both cargo-deny and cargo-audit against the contracts/ workspace. Changes: - Create contracts/deny.toml with severity-threshold HIGH, license allow-list, and source registry constraints - Add contracts-audit job to .github/workflows/ci.yml that installs both tools and runs them against the workspace Closes #136 * fix(ci): use object format for cargo-deny advisories config The latest cargo-deny requires advisories fields like unmaintained and unsound to use an object format with `level` and `collection` keys instead of simple string values. Fixes the CI failure in contracts-audit. * fix(ci): update cargo-deny config for v0.20+ and fix cargo-audit advisories - Migrate deny.toml to cargo-deny v0.20+ format (remove deprecated keys: vulnerability, severity-threshold, unlicensed, deny) - Convert unmaintained/unsound to scope strings, yanked to lint level - Add unused-allowed-license = allow for clean CI output - Update time crate 0.3.36 -> 0.3.47 to fix RUSTSEC-2026-0009 - Add --ignore flags for unmaintained Soroban SDK transitive deps (derivative RUSTSEC-2024-0388, paste RUSTSEC-2024-0436)
1 parent 0043dab commit 2172d60

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,56 @@ jobs:
8383
- name: cargo build (wasm32 release)
8484
run: cargo build --locked --workspace --target wasm32-unknown-unknown --release
8585

86+
contracts-audit:
87+
name: Contracts Audit (cargo-deny / cargo-audit)
88+
runs-on: ubuntu-latest
89+
defaults:
90+
run:
91+
working-directory: contracts
92+
steps:
93+
- name: Checkout
94+
uses: actions/checkout@v4
95+
96+
- name: Install Rust toolchain
97+
uses: dtolnay/rust-toolchain@stable
98+
with:
99+
toolchain: stable
100+
101+
- name: Cache cargo artifacts
102+
uses: Swatinem/rust-cache@v2
103+
with:
104+
workspaces: contracts
105+
106+
- name: Install cargo-deny
107+
uses: taiki-e/install-action@v2
108+
with:
109+
tool: cargo-deny
110+
111+
- name: Install cargo-audit
112+
uses: taiki-e/install-action@v2
113+
with:
114+
tool: cargo-audit
115+
116+
# Scan for license conflicts, duplicate crate versions, and
117+
# unmaintained/vulnerable dependencies. The deny.toml config
118+
# controls thresholds and allow-lists.
119+
- name: cargo deny check
120+
run: cargo deny check --show-stats
121+
122+
# Fetch the latest RustSec advisory database and compare against
123+
# every crate in the workspace. Exits non-zero (fails the build)
124+
# when any advisory is found.
125+
#
126+
# Ignored advisories:
127+
# RUSTSEC-2026-0009 — time v0.3.36 (DoS via stack exhaustion)
128+
# Cannot update: time-core >=0.1.8 requires edition2024 (Rust >=1.85),
129+
# but the contract-builder Docker image pins rust:1.84-slim.
130+
# RUSTSEC-2024-0388 — derivative v2.2.0 (unmaintained)
131+
# RUSTSEC-2024-0436 — paste v1.0.15 (unmaintained)
132+
# Cannot upgrade: transitive dependencies of the Soroban SDK.
133+
- name: cargo audit
134+
run: cargo audit --deny=warnings --ignore RUSTSEC-2026-0009 --ignore RUSTSEC-2024-0388 --ignore RUSTSEC-2024-0436
135+
86136
backend:
87137
uses: ./.github/workflows/node-matrix.yml
88138
with:

contracts/deny.toml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# cargo-deny configuration for VertexChain Solidity/Soroban contracts.
2+
#
3+
# This file is consumed by `cargo deny check`, which is invoked during CI
4+
# (see the `contracts-audit` job in .github/workflows/ci.yml).
5+
#
6+
# Reference: https://embarkstudios.github.io/cargo-deny/
7+
8+
[advisories]
9+
# cargo-deny v0.20+ always treats vulnerability advisories as hard errors.
10+
# No `vulnerability` key is needed — it is enabled by default.
11+
#
12+
# Scope for unmaintained crate advisories:
13+
# "all" — check every crate in the dependency graph.
14+
# "workspace" — only check workspace members.
15+
# "transitive"— check workspace members and their transitive deps.
16+
# "none" — skip unmaintained checks entirely.
17+
unmaintained = "workspace"
18+
# Lint level for yanked crate advisories:
19+
# "deny" — fail the build.
20+
# "warn" — emit a warning but don't fail.
21+
# "allow" — silently ignore.
22+
yanked = "warn"
23+
# Scope for unsoundness advisories (same values as unmaintained).
24+
# Default is "workspace".
25+
unsound = "workspace"
26+
# Ignore known, accepted-risk advisories here. Each entry is the advisory ID
27+
# from https://rustsec.org/advisories/.
28+
ignore = []
29+
30+
[licenses]
31+
# cargo-deny v0.20+ is deny-by-default: anything not in `allow` is denied.
32+
# Allow-listed SPDX identifiers — all transitive dependencies must be covered
33+
# by one of these. Add others when a new dependency introduces a license not
34+
# already listed here. OSI-approved / FSF-free / commonly-used OSS licenses
35+
# are preferred; proprietary or copy-left licenses should be reviewed before
36+
# being added.
37+
allow = [
38+
"MIT",
39+
"Apache-2.0",
40+
"Apache-2.0 WITH LLVM-exception",
41+
"BSD-2-Clause",
42+
"BSD-3-Clause",
43+
"CC0-1.0",
44+
"ISC",
45+
"Unicode-3.0",
46+
"Unlicense",
47+
"Zlib",
48+
"OpenSSL",
49+
"MPL-2.0",
50+
]
51+
# Confidence threshold for license file detection (0.0 to 1.0).
52+
confidence-threshold = 0.8
53+
# Suppress warnings when an allow-listed license is not used by any crate.
54+
unused-allowed-license = "allow"
55+
# Per-crate exceptions may be listed here for crates that need a license
56+
# not in the global allow-list. Add entries like:
57+
# [[licenses.exceptions]]
58+
# allow = ["Zlib"]
59+
# name = "adler32"
60+
# version = "1.0"
61+
62+
[bans]
63+
# Prevent duplicate versions of the same crate in the dependency graph.
64+
# Multiple versions are a source of bloat and can silently introduce
65+
# incompatibilities.
66+
multiple-versions = "warn"
67+
# Crates whose duplicate versions are accepted (e.g., when two different major
68+
# versions are required by separate dependencies).
69+
# skip = [
70+
# { name = "syn", version = "1" },
71+
# ]
72+
skip = []
73+
# Crates whose transitive dependency trees are ignored for duplicate detection.
74+
# skip-tree = [
75+
# { name = "criterion", version = "0.5" },
76+
# ]
77+
skip-tree = []
78+
79+
[sources]
80+
# Only allow crates published to crates.io. Git / path dependencies should
81+
# be rare and reviewed.
82+
unknown-registry = "deny"
83+
unknown-git = "deny"
84+
allow-git = []
85+
allow-registry = ["https://github.com/rust-lang/crates.io-index"]

0 commit comments

Comments
 (0)