Skip to content

fix(ci): pin the bridge-gate scanner and make the B1 verdict require a queried feed - #488

Merged
hyperpolymath merged 3 commits into
mainfrom
marina/optimistic-cray-js64k7
Nov 10, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
marina/optimistic-cray-js64k7

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Closes #481.

bridge-gate.yml built panic-attack from its moving main (CWE-829), and its B1 verdict trusted any report. This pull request pins the scanner and makes B1 refuse a report whose feed was not queried.

It also repairs a defect that the issue does not name: B1 could never fail. The step selected "Unmitigable" and "Reachable". The scanner at the pinned commit writes "unmitigable" and "reachable", so the filter matched nothing and B1 passed for every report.

The two commits are separate reviews: the pin first, then the verdict.

Changes

  • Pin (commit 1). The job builds panic-attack at the commit that static-analysis-gate.yml pins in PANIC_ATTACK_REF.
    • The job reads that value with yq, so the pin has one owner and the two workflows cannot use different scanners.
    • A missing or floating value builds nothing and exits 2.
    • The build is the one the Static Analysis Gate uses: cargo install --git --rev --locked, a check that .crates.toml names that revision, and a build receipt with the binary digest.
  • Verdict (commit 2). The verdict moves into scripts/ci/static-analysis-evidence.sh as bridge-b1.
    • The triage step now runs the existing adapter. It qualifies only a complete schema 0.3.0 report whose vulnerability_data is queried.
    • bridge-b1 exits 2 when the receipt is not a qualified Patch Bridge receipt.
    • It also exits 2 when a CVE has a reachability status outside the four known values. A renamed value therefore cannot pass in silence.
    • It exits 1 for a reachable unmitigable CVE, with the real values.
  • No uses: reference changes, so actions.lock is unchanged.

RSR Quality Checklist

Required

  • Tests pass (just test or equivalent). Equivalent here: bash scripts/ci/test-static-analysis-evidence.sh, 59 controls. just test was not run; no Rust source changes.
  • Code is formatted (just fmt or equivalent). Not run: the change is shell and workflow YAML only.
  • Linter is clean (no new warnings or errors). Not run locally: no shellcheck or actionlint on this machine. bash -n passes for both scripts.
  • No banned language patterns (no , no npm/bun, no Go/Python)
  • No unsafe blocks without // SAFETY: comments (no Rust changes)
  • No banned functions (believe_me, unsafeCoerce, Obj.magic, Admitted, sorry)
  • SPDX license headers present on all new/modified source files
  • No secrets, credentials, or .env files included

As Applicable

  • Repo deed (*_chora.deed) (status) / (maturity) updated (if project state changed)
  • Repo deed (ecosystem) updated (if integrations changed)
  • Repo deed (meta) and/or docs/decisions/ updated (if architectural decisions changed)
  • docs/status/ROADMAP.adoc updated (if milestones or next actions changed)
  • Documentation updated for user-facing changes
  • TOPOLOGY.md updated (if architecture changed)
  • CHANGELOG or release notes updated
  • New dependencies reviewed for license compatibility (MPL-2.0 / MPL-2.0)
  • ABI/FFI changes validated (src/abi/ and ffi/zig/ consistent)

None of these applies: the change is confined to one CI gate and its script.

Testing

Controls. scripts/ci/test-static-analysis-evidence.sh runs on every pull request in the Static Analysis Gate.

  • 36 controls before, 59 now. The 36 earlier controls pass unchanged against the new script.
  • New controls: a reachable unmitigable CVE gives exit 1. The same CVE gives exit 0 when it is unreachable, phantom or mitigable. A report with offline-unavailable or no-dependencies gives exit 2. A receipt edited to carry an unqueried report gives exit 2. The old spelling Reachable gives exit 2.
  • Three mutants of bridge-b1 each fail the controls: the old capitalised values, no refusal of an unknown status, and no qualified-receipt requirement.

Real scanner, local. I extracted the three changed steps from the workflow file and ran them on this tree (x86_64 Linux, cargo 1.99.0).

Step Result
Build at f2a6a70 Passes. .crates.toml names the revision. Binary digest db940771....
Triage through the adapter Exit 0. Schema 0.3.0, vulnerability_data: queried, 501 dependencies, 1 informational CVE (phantom-transitive).
bridge-b1 Exit 0: B1 PASS.

Real scanner, forced offline (control). The same binary with --offline writes vulnerability_data: offline-unavailable and 0 CVEs. The adapter exits 2 and bridge-b1 exits 2. The earlier B1 step counts 0 blockers for that report and prints PASS.

Not run on GitHub. bridge-gate.yml runs only on dependabot/ and renovate/ branches, so this pull request does not execute the job. The next dependency pull request is the first hosted run.

Screenshots

Not applicable.


Generated by Claude Code

bridge-gate.yml cloned panic-attack with --depth 1 and built whatever
was on its main at run time. The same commit could pass or fail by the
time of the run, and a change in panic-attack ran in this CI without
review here (CWE-829).

Build at the commit that static-analysis-gate.yml pins in
PANIC_ATTACK_REF. This job reads that value with yq, so the pin has one
owner and the two workflows cannot use different scanners. A missing or
floating value builds nothing and exits 2.

The build is the one the Static Analysis Gate uses: cargo install
--git --rev --locked, a check that .crates.toml names that revision,
and a build receipt with the binary digest.

No uses: reference changes, so actions.lock is unchanged.

Refs #481

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0136P7ZmAsYpFA9gxfQLF3F6
Signed-off-by: Claude <noreply@anthropic.com>
Two defects in the bridge-gate B1 step.

It trusted any report. Patch Bridge schema 0.3.0 adds
vulnerability_data: a report with "offline-unavailable" or
"no-dependencies" has an empty CVE list because no feed was read. B1
read that as zero CVEs and passed.

It could never fail. The step selected classification "Unmitigable" and
reachability status "Reachable". The scanner at the pinned commit
writes "unmitigable" and "reachable" (serde lowercase and kebab-case),
so the filter matched nothing and B1 passed for every report.

Move the verdict into scripts/ci/static-analysis-evidence.sh as
bridge-b1, next to the adapter that the Static Analysis Gate uses:

- the triage step now runs the adapter, which checks the binary against
  its build receipt and qualifies only a complete 0.3.0 report whose
  vulnerability_data is "queried";
- bridge-b1 exits 2 when the receipt is not a qualified Patch Bridge
  receipt, and also when a CVE has a reachability status outside the
  four known values, so a renamed value cannot pass in silence;
- it exits 1 for a reachable unmitigable CVE, with the real values.

Controls in scripts/ci/test-static-analysis-evidence.sh, which the
Static Analysis Gate runs on every pull request: 36 before, 59 now.
The 36 earlier controls pass unchanged against the new script. Three
mutants fail the controls: the old capitalised values, no refusal of an
unknown status, and no qualified-receipt requirement.

bridge-gate.yml runs only on dependabot/ and renovate/ branches, so
this pull request does not execute the job itself.

Refs #481

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0136P7ZmAsYpFA9gxfQLF3F6
Signed-off-by: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Caution

Review failed

The pull request is closed.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@hyperpolymath
hyperpolymath marked this pull request as ready for review November 10, 2026 17:17
@hyperpolymath
hyperpolymath enabled auto-merge (squash) November 10, 2026 17:17
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T17:19:48.747233Z 67ea81a Draft marked ready
🔒 Security Review ❌ Failed 2026-11-10T17:17:30.153189Z
We couldn’t complete this review. Comment @codex security review to try again.
67ea81a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins.

hyperpolymath commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner Author

Two checks fail here, and both fail on main too. This pull request does not cause either.

1. panic-attack assail

  • Here (head 67ea81a, run 42862713555): the last step, "Require completed scan and reject critical findings", exits 1.
    • Every earlier step passed, including "Verify scanner receipt controls". That step runs the 59 controls of this pull request on the hosted runner.
  • On main (f546ee9, the base of this pull request, run 42743730452): the Static Analysis Gate has the conclusion failure.
  • Same findings on both trees. I ran the pinned scanner (f2a6a70) locally on both. Each has 2 unsuppressed Critical findings, both ProofDrift, one sorry each:
    • tests/corpus_fixtures/isabelle/Smoke.thy
    • tests/corpus_fixtures/minif2f/algebra.lean
  • This pull request does not touch those files.

No fix exists yet: I found no open pull request for it, and audits/assail-classifications.a2ml has no entry for either file. I did not widen this pull request.

Two ways to repair it, for the owner to choose:

  1. Fix at the source: remove or replace the sorry in the two fixtures, if the tests do not need it.
  2. Record both files in audits/assail-classifications.a2ml with an audit rationale. That grows a ledger, so it needs a Ratchet-exception: line.

2. governance / Validate Hypatia Baseline

The log names the two repairs: fix each finding, or add it to .hypatia-baseline.json with a note.


Generated by Claude Code

SonarCloud reported shell:S7679 three times on bridge_report in
scripts/ci/test-static-analysis-evidence.sh: the helper used $1, $2
and $3 directly. Assign them to local names. No behaviour change: the
59 controls pass.

Refs #481

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0136P7ZmAsYpFA9gxfQLF3F6
Signed-off-by: Claude <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit b6ff166 into main Nov 10, 2026
70 of 73 checks passed
@hyperpolymath
hyperpolymath deleted the marina/optimistic-cray-js64k7 branch November 10, 2026 17:27
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.

bridge-gate.yml builds panic-attack from moving main (unpinned scanner, CWE-829)

3 participants