Skip to content

cargo-audit and cargo-deny check advisories with different policies, and have drifted #123

Open

Description

@gvonnessi

cargo audit and cargo deny both check advisories in the Security Audit job, with
different policies, from different files. They have drifted, and on 2026-08-20 they
disagreed in a way that cost a full CI round trip to notice.

What happened

Two months of drift left the job red. cargo audit was failing on two advisories with clean
upgrade paths, which were fixed (#122). Step 7 Audit dependencies went green — and step 9
Check dependency policies stayed red, on an advisory that had been in cargo audit's own
output the entire time, counted among its "5 allowed warnings":

error[unsound]: Unsoundness in `Error::downcast_mut()`
   ├ ID: RUSTSEC-2026-0190
advisories FAILED, bans ok, licenses ok, sources ok

cargo audit treats informational = "unsound" as a warning. cargo deny treats it as
error[unsound]. Same advisory database, same lockfile, opposite verdicts. That is not a bug in
either tool — it is two policies with no single owner.

The concrete divergence

cargo audit (in ci.yml) cargo deny (in deny.toml)
RUSTSEC-2023-0071 (rsa Marvin) ignored ignored
RUSTSEC-2026-0037 ignored not listed
yanked crates warn (default) yanked = "warn" (explicit)
informational = "unsound" warn error

RUSTSEC-2026-0037 is suppressed in one tool and unknown to the other. Whichever way that
advisory would land, only one of the two is expressing the intent.

Why it is worth a decision rather than a patch

deny.toml's entries are not incidental — each carries a rationale and a dated review:

  • yanked = "warn" — "RustCrypto RC ecosystem has transiently yanked digest/cipher/crypto-common
    0.11.x. Non-yanked replacements (0.11.2+) break hkdf/universal-hash/ctr." Last reviewed 2026-03-13.
  • ignore = ["RUSTSEC-2023-0071"] — "signatures-rsa is opt-in (not in default features)."
    Last reviewed 2026-02-16.

Those are real judgements about this crate's exposure. Reconciling the two configs means
re-taking them, and deciding which file is the source of truth, which is why #122 fixed the
advisory and deliberately left this alone.

Options

  1. deny.toml becomes authoritative. Move ci.yml's --ignore flags into it so one file
    holds the policy and the dated review notes sit with the decisions they justify.
  2. Split responsibilities. cargo audit owns advisories; cargo deny drops its advisories
    check and keeps bans/licenses/sources, which it already reports separately. Removes the
    overlap — but loses deny's stricter treatment of unsound advisories, which is what caught
    RUSTSEC-2026-0190 in the first place.
  3. Keep both, sync the lists, and add a note to each file pointing at the other.

Whatever is chosen, the failure mode to design against is the one seen here: a green
cargo audit reading as "advisories are clean" when a second tool disagrees.

Found while adding fork-PR run caps (#122).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions