Skip to content

Audit dependencies on every pull request, not only those targeting master - #401

Merged
lamemustafa merged 1 commit into
masterfrom
fix/dependency-security-trigger
Sep 15, 2026
Merged

lamemustafa merged 1 commit into
masterfrom
fix/dependency-security-trigger

Conversation

@lamemustafa

Copy link
Copy Markdown
Owner

Follow-up to #398, which fixed the identical filter in ci.yml. A review of that PR flagged this file as carrying the same bug, unfixed.

dependency-security.yml filtered pull_request to branches: [master], so a PR stacked on another branch got no cargo-audit and no frontend dependency audit at all — while still reporting a green mergeable state, because nothing required had failed. That is the same false green #398 describes, in the workflow whose entire job is to tell you about an advisory.

Why this is worth its own change rather than living with

The cost differs from ci.yml's. A missing test run delays a signal about code the PR contains — bounded by that PR. A missing dependency audit delays a signal about a published advisory that may already apply, and the delay runs until the stack root merges. The advisory then surfaces attached to whichever PR happens to land first, not to the one that introduced the dependency.

push stays master-only for the reason ci.yml gives: a branch worth auditing has a pull request, and that is what triggers the run.

Verification

Every exit status read directly, not through a pipe.

check result
reseal.sh --verify exit 0
check-ci-workflow-consistency.mjs exit 0
compatibility gate compatibility_gate_passed:unknown_claims=11:evidenced_claims=0
tools workspace 11 binaries, 53 passed, 0 failed

dependency-security.yml is in the compatibility surface, so surface and matrix are resealed: one hash changed, pin set set-compared against master and unchanged at 212, and the recorded sha256 independently recomputed against the file's bytes. The workflow parses and keeps its single audit job, with pull_request now carrying only types.

Scope

Only the trigger. The audit job, its permissions: contents: read, and its concurrency group are untouched. This workflow has no secrets.* usage and is pull_request, not pull_request_target, so fork-PR exposure is unchanged — the same reasoning that held for #398.

After this, docs/proposed-merge-gate-ci.md:44-45 is the last place the old pattern appears. It is a proposal doc rather than a live workflow, and arguably correct for a master-branch-protection gate specifically, so it is left alone here.

🤖 Generated with Claude Code

…ster

`dependency-security.yml` carried the same `pull_request: branches: [master]`
filter #398 removed from `ci.yml`, so a pull request stacked on another branch
got no `cargo-audit` or frontend dependency audit at all. It still reported a
green mergeable state, because nothing required had failed -- the same shape
of false green, in the workflow whose whole job is to tell you about an
advisory.

The cost of the gap is different from `ci.yml`'s, which is why it is worth
fixing separately rather than living with. A missing test run delays a signal
about code the PR contains. A missing dependency audit delays a signal about a
published advisory that may already apply, and the delay lasts until the stack
root merges -- so the advisory surfaces attached to whichever PR happens to
land first, not to the one that introduced the dependency.

`push` stays master-only for the reason `ci.yml` gives: a branch worth auditing
has a pull request, and that is what triggers the run.

`dependency-security.yml` is in the compatibility surface, so surface and
matrix are resealed: one hash changed, pin set unchanged at 212 (set-compared
against master, not counted), and the recorded sha256 matches the file's bytes.

Verified with every exit status read directly: `reseal.sh --verify` exit 0;
`check-ci-workflow-consistency.mjs` exit 0; compatibility gate passes; tools
workspace 11 binaries, 53 passed, 0 failed. The workflow parses and keeps its
single `audit` job, with `pull_request` now carrying only `types`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@lamemustafa

Copy link
Copy Markdown
Owner Author

Review turned up one consequence worth recording before this merges. It is not a defect in the diff, and it does not block — but it is a real cost that this change widens, and it should be on the PR rather than only in a review transcript.

Widening the trigger widens the blast radius of a failure mode that fired today.

scripts/check-advisory-delta.mjs documents it in its own header: on 2026-09-15, RUSTSEC-2026-0285 was published against rustls (transitively via reqwest), and cargo audit on an unchanged master went from a clean pass to error: 1 vulnerability found! with no change on our side. Because "Dependency security" is a required status check, that single external event turned all 9 then-open PRs red at once, including ones with nothing to do with rustls. The script's own words: "the blocking mechanism was wrong: a PR should fail because IT introduced new exposure, not because the outside world changed under an unrelated branch."

This workflow still runs plain, non-differential cargo audit --file src-tauri/Cargo.lock (line 44). The differential gate that fixes it — scripts/check-advisory-delta.mjs, which compares advisory sets across two lockfile states — exists and has contract tests, but is wired into nothing: the only reference to it anywhere under .github/ or scripts/ is its own test file. docs/proposed-dependency-policy.md says so explicitly, that its CI wiring is proposed rather than applied.

So after this change, the next external advisory publication turns every open PR red rather than only master-targeting ones.

Merging anyway, for two reasons:

  1. The alternative is the bug being fixed — stacked PRs getting no dependency audit at all, which is strictly worse than getting a noisy one. A red audit on a stacked PR is information; its absence was a false green.
  2. Required status checks gate merges into the branch carrying the protection rule, so a non-master-targeting PR going red here is noise rather than a block.

The real fix is to wire check-advisory-delta.mjs into this workflow, which would make an advisory fail the PR that introduced it rather than every PR open when it was published. That is a separate change with its own review, and this one makes it more valuable rather than less.

@lamemustafa
lamemustafa merged commit 770eb76 into master Sep 15, 2026
11 checks passed
@lamemustafa
lamemustafa deleted the fix/dependency-security-trigger branch September 15, 2026 17:55
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.

1 participant