Skip to content

fix(ci): flip cargo-audit + cargo-deny from advisory to required (SEV-011 Medium)#333

Merged
alrimarleskovar merged 5 commits into
mainfrom
fix/sev-011-cargo-audit-deny-required
May 15, 2026
Merged

fix(ci): flip cargo-audit + cargo-deny from advisory to required (SEV-011 Medium)#333
alrimarleskovar merged 5 commits into
mainfrom
fix/sev-011-cargo-audit-deny-required

Conversation

@alrimarleskovar
Copy link
Copy Markdown
Owner

Adevar Labs audit — Fase 2 PR-D. Closes Medium-severity SEV-011. Final code PR of Fase 2.

Summary

Both cargo audit and cargo deny lanes were shipped with || true ("advisory-only") because the Solana 1.18 / mpl-core 0.8 dep tree carries known-transient advisories unfixable from our side. Result: green CI even when NEW advisories landed against non-Solana deps. Silently. Falsa sensação de segurança.

What changed

# Before (advisory)
- name: cargo audit (advisory-only on day 1)
  run: cargo audit || true

# After (required)
- name: cargo audit (required, Solana 1.18 transients ignored)
  run: |
    cargo audit \
      --deny warnings \
      --ignore RUSTSEC-2024-0344 \
      --ignore RUSTSEC-2022-0093 \
      # ... 9 more, each tied to the upstream cause + retire condition

Same flip on the cargo deny lane + parity-list in deny.toml [advisories].ignore.

The 11 ignored RUSTSEC-IDs

All currently flagged by cargo audit; all from Solana 1.18 / mpl-core 0.8 transitives:

ID Cause
RUSTSEC-2024-0344 curve25519-dalek timing variability
RUSTSEC-2022-0093 ed25519-dalek double-PK signing oracle
RUSTSEC-2024-0375 atty unmaintained
RUSTSEC-2021-0145 atty unaligned read
RUSTSEC-2025-0141 bincode unmaintained
RUSTSEC-2024-0388 derivative unmaintained
RUSTSEC-2025-0161 libsecp256k1 unmaintained
RUSTSEC-2024-0436 paste unmaintained
RUSTSEC-2024-0370 proc-macro-error unmaintained
RUSTSEC-2023-0033 borsh 0.x ZST unsoundness (mpl-core 0.8 transitive)
RUSTSEC-2026-0097 rand unsound with custom logger

When the Agave 2.x migration (#319) lands, the bulk retire automatically (Solana 2.x ships fixed versions). The follow-up PR on that branch sweeps the ignore list down — any ID that survives gets explicit triage rather than silent-pass.

What this gate now catches

A NEW advisory against ANY non-Solana dep (serde, tokio, prisma, axum, etc.) lands as a red CI check on the PR that introduced it. Reviewer sees the RUSTSEC ID and affected crate before merge. Exactly the visibility lost in the || true posture.

Validation

Ran locally on this branch:

$ cargo audit --deny warnings --ignore <11 IDs>
  Loaded 1090 security advisories
  Scanning Cargo.lock for vulnerabilities (382 crate dependencies)
  exit=0 ✓

$ pnpm lint
  All matched files use Prettier code style! ✓

Cost: <30s cached, ~1m cold — negligible for a required gate.

Fase 2 status after this PR

PR SEVs Status
#330 F2-A: 009 + 013 + 010 ✅ Open
#331 F2-B: 006 ✅ Open
#332 F2-C: 007 + 008 ✅ Open
This PR F2-D: 011 ✅ Open
(deferred) F2-E: 012 bankrun-in-CI Blocked on #319

Fase 2 code track complete (4/4 PRs open). Only F2-E (bankrun-in-CI) remains, blocked upstream on #319.


Generated by Claude Code

…-011 Medium)

Closes Adevar Labs SEV-011 (Medium). The cargo-audit and cargo-deny
lanes were both shipped with `|| true` ("advisory-only") because the
Solana 1.18 / mpl-core 0.8 dep tree carries a handful of transient
advisories that are unfixable from our side until the Agave 2.x
migration (#319) completes. Result: green CI even when NEW advisories
landed against non-Solana deps (serde, tokio, prisma, ...) —
silently. Falsa sensação de segurança.

What changed
============

.github/workflows/ci.yml:
  audit lane:
    - `name`: "audit · cargo-audit (advisory)" → "audit · cargo-audit (required)"
    - Command: `cargo audit || true` → `cargo audit --deny warnings --ignore <11 RUSTSEC-IDs>`
    - Each ignore commented inline with the upstream cause + retire
      condition (Agave 2.x landing)

  deny lane:
    - `name`: "deny · supply-chain (advisory)" → "deny · supply-chain (required)"
    - Command: `cargo deny check ... || true` → `cargo deny check`
    - Same RUSTSEC-IDs listed in deny.toml `[advisories].ignore`
      for parity with cargo-audit

deny.toml `[advisories].ignore`:
  Was: 3 placeholder comments (`# "RUSTSEC-YYYY-NNNN", # ...`)
  Now: 11 explicit RUSTSEC-IDs, one per known-transient, with the
       same comment + retire condition as the CI workflow

The 11 ignored RUSTSEC-IDs
==========================

All currently flagged by `cargo audit` against this branch; all from
the Solana 1.18 / mpl-core 0.8 transitive dep tree:

  RUSTSEC-2024-0344  curve25519-dalek timing variability
                     (solana-zk-token-sdk 1.18 transitive)
  RUSTSEC-2022-0093  ed25519-dalek double-PK signing oracle
                     (solana-sdk 1.18 transitive)
  RUSTSEC-2024-0375  atty unmaintained
  RUSTSEC-2021-0145  atty unaligned read
  RUSTSEC-2025-0141  bincode unmaintained
  RUSTSEC-2024-0388  derivative unmaintained
  RUSTSEC-2025-0161  libsecp256k1 unmaintained
  RUSTSEC-2024-0436  paste unmaintained
  RUSTSEC-2024-0370  proc-macro-error unmaintained
  RUSTSEC-2023-0033  borsh 0.x ZST unsoundness (mpl-core 0.8 transitive)
  RUSTSEC-2026-0097  rand unsound with custom logger

When the Agave 2.x migration (#319) lands, the bulk of these retire
automatically (Solana 2.x ships fixed versions). The follow-up PR
on that branch will sweep the ignore list down to zero — any ID
that survives gets explicit triage rather than silent-pass.

What this gate now catches
==========================

A NEW advisory against ANY non-Solana dep (serde, tokio, prisma,
axum, etc.) lands as a red CI check on the PR that introduced it.
Reviewer sees the RUSTSEC ID and the affected crate before merge.
Exactly the visibility we lost in the `|| true` posture.

Validation
==========

Ran locally on this branch:

  $ cargo audit --deny warnings --ignore <11 IDs>
    Loaded 1090 security advisories
    Scanning Cargo.lock for vulnerabilities (382 crate dependencies)
    exit=0 ✓

  $ pnpm lint
    All matched files use Prettier code style! ✓

The audit lane runs in <30s for cached + ~1m cold, so the CI cost
of flipping from advisory to required is negligible.

Closes Fase 2 PR-D of the Adevar Labs remediation plan.

https://claude.ai/code/session_01YapZy1Z5gzbV5EammBkSQm
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
round_financial Ignored Ignored May 15, 2026 1:14pm

… clarify + bans tolerance

CI lane failure on PR #333: `deny · supply-chain (required)` was
failing because cargo-deny treats workspace path deps as wildcards
unless `publish = false` is set on each member crate. Also failed
license detection for mpl-core 0.8.1 (no `license` field in the
crate's Cargo.toml, only a LICENSE file).

Three changes to make cargo-deny pass against the actual dep tree:

1. **Cargo.toml** — added `publish = false` to [workspace.package]
   and `publish.workspace = true` to each of the 5 member crates.
   These are Solana programs + math lib, never destined for
   crates.io. Declares intent + unlocks cargo-deny's
   `allow-wildcard-paths` honoring.

2. **deny.toml [bans]** — added `allow-wildcard-paths = true`. With
   `publish = false` set on the workspace, cargo-deny now accepts
   intra-workspace `path = "../..."` deps without flagging them as
   wildcards.

3. **deny.toml [[licenses.clarify]]** — added a clarify entry for
   `mpl-core 0.8.1`. The crate ships a LICENSE file (Apache-2.0) but
   doesn't declare the license field in Cargo.toml. cargo-deny's
   text-fingerprint heuristic gets 0.80 confidence — below the 0.93
   threshold — so the clarify entry pins the resolution explicitly.
   Retires when we upgrade to mpl-core 0.12 (which declares its
   license field properly) via the Agave 2.x migration (#319).

Validation
==========

  $ cargo generate-lockfile          # CI does this
  $ cargo deny check --hide-inclusion-graph
    advisories ok, bans ok, licenses ok, sources ok ✓

  $ cargo audit --deny warnings --ignore <11 IDs>
    exit=0 ✓

  $ pnpm lint                         # green
  $ cargo check -p roundfi-core       # green

All four cargo-deny gates pass. Cargo.toml additions are pure
metadata — no semantic impact on the build.

Continues SEV-011 remediation; this commit is the test-against-fresh-
lockfile follow-up that the original ci.yml flip missed.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/alrimarleskovars-projects?upgradeToPro=build-rate-limit

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

🟢 Coverage Report — roundfi-math

Metric Value
Coverage 90.91%
Lines 110/121 lines covered
Threshold 85%
Status ✅ meets threshold

Scope: roundfi-math only. Full-workspace coverage gated on Agave 2.x migration (#230).

alrimarleskovar and others added 3 commits May 15, 2026 14:28
…tection compat

The previous commit renamed the lanes to "(required)" to reflect
their flipped semantics, but branch protection still pins the exact
old name "audit · cargo-audit (advisory)" + "deny · supply-chain
(advisory)". Renaming made the merge gate report "expected check
missing" against #333's own merge.

Reverting just the lane names — the gate semantics (no `|| true`,
--deny warnings, explicit --ignore list) all stay. Doc comment on
each lane notes the name/semantics mismatch + the path to flip
when branch protection updates the rule.
@alrimarleskovar alrimarleskovar merged commit 1b85111 into main May 15, 2026
11 of 12 checks passed
alrimarleskovar pushed a commit that referenced this pull request May 15, 2026
The previous "second-pass" audit (ADEVAR_AUDIT_REPORT_PASS_2.md) was
executed against the original snapshot fbc931e — NOT against the
current main with 15 merged fix commits. The team correctly flagged
this. Root cause: failed to `git fetch origin main` before reading
files; the local branch was forked at the pre-fix commit so every
finding was "re-confirmed" against vulnerable code that no longer
existed upstream.

This corrected re-audit verifies against main HEAD e227d95:

✅ 16 findings FIXED (with explicit commit + PR references):
- SEV-001 → #326 (c_token_account ATA constraint)
- SEV-002 → #327 (GRACE_PERIOD_SECS 60s → 7d)
- SEV-003/004/005 → #329 (lp_share_bps to config, vaults_initialized
  flag, PoolStatus::Closed terminal state)
- SEV-006 → #331 (treasury USDC ATA validation)
- SEV-007/008 → #332 (level demotion on default + verified_at_attest)
- SEV-009/010/013 → #330 (webhook auth + B2B salt + salt entropy)
- SEV-011 → #333 (cargo-audit required, no || true)
- SEV-014 → #336 (decoder prefix fix)
- SEV-015 → #335 (cancel_pending_listing)
- SEV-016/017 → #334 (release_escrow partial-pay + nft_asset doc)
- SEV-019/020 → #328 (docs hardening)

❌ 10 findings STILL OPEN against main:
- SEV-012 (bankrun CI — blocked on Agave 2.x upstream)
- SEV-018 (informational, design intent)
- SEV-021/022 (reputation authority/pause asymmetry — High)
- SEV-023/024 (MIN_CYCLE_DURATION 60s, fee_bps_yield 100% cap)
- SEV-025/026/027/028 (pool solvency, cascade refactor, payment
  cooldown, refresh error handling)

Score updated: 6.0 (wrong) → 7.5/10 against actual main.
Recommendation changed: NÃO DEPLOY → DEPLOY EM CANARY COM RESSALVAS
(SEV-001..SEV-005 all closed; SEV-021/022 must close before
canary cap removal).

https://claude.ai/code/session_01CiaV9hd9oFqqr7m9ANgfit
@alrimarleskovar alrimarleskovar deleted the fix/sev-011-cargo-audit-deny-required branch May 17, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants