feat(ci): adopt canonical no-dedup bypass-audit standard#181
Conversation
Replace the dedup-based admin-bypass audit with the canonical no-dedup design (helmet ADR-0001, pipeline v1.21.1): identity-based skip only, fail-on-indeterminate, exact-label existence check, separated stderr on the PR lookup, and contents:read for private-repo PR association. Dedup via mutable issue metadata is an insider-editable suppression vector; for org repos the org audit log is the authoritative trail. Stamped # helmet-pipeline: v1.21.1 for drift detection. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
📝 WalkthroughWalkthroughThe workflow's documentation, concurrency model, and core audit detection logic are refactored. The header now explicitly describes the push-time audit design and its accepted limitations. Identity-based actor skipping replaces commit-message checks. PR API failures and summary issue creation errors set AUDIT_FAILED and cause a non-zero exit. A single labeled-first summary issue consolidates detected bypasses. ChangesBypass Audit Workflow Refactor
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Warning Review ran into problems🔥 ProblemsStopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a 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. Comment |
The attacker-controlled commit message was rendered inside a fenced code block in the audit issue; a fence marker (or a carriage return) in the message could break out and inject Markdown. Render it as an indented code block with CR stripped — which cannot be broken out of. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/bypass-audit.yml (1)
92-97:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPersist the push pre-SHA and compare range in the audit issue.
The workflow issue body currently records only the head
COMMIT_SHA(commit link) and the first 3 lines of the head commit message; it omitsgithub.event.before, so reviewers can’t reconstruct the fullbefore…afterrange for multi-commit pushes.🧾 Proposed fix
env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BEFORE_SHA: ${{ github.event.before }} COMMIT_SHA: ${{ github.sha }} ACTOR: ${{ github.actor }} REPO: ${{ github.repository }} COMMIT_MSG: ${{ github.event.head_commit.message }} RUN_ID: ${{ github.run_id }} @@ printf '| Field | Value |\n' printf '|-------|-------|\n' printf '| **Commit** | [\`%s\`](https://github.com/%s/commit/%s) |\n' "$COMMIT_SHA" "$REPO" "$COMMIT_SHA" + if [ "$BEFORE_SHA" != "0000000000000000000000000000000000000000" ]; then + printf '| **Range** | [\`%s...%s\`](https://github.com/%s/compare/%s...%s) |\n' \ + "$BEFORE_SHA" "$COMMIT_SHA" "$REPO" "$BEFORE_SHA" "$COMMIT_SHA" + fi printf '| **Actor** | @%s |\n' "$ACTOR" printf '| **Workflow run** | [%s](https://github.com/%s/actions/runs/%s) |\n' "$RUN_ID" "$REPO" "$RUN_ID" printf '| **Time (UTC)** | `%s` |\n\n' "$NOW"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/bypass-audit.yml around lines 92 - 97, The audit issue body currently only records COMMIT_SHA and COMMIT_MSG; update the workflow to also capture and persist the pre-push SHA (github.event.before) and a full compare range string (e.g., "{github.event.before}..{github.sha}") so reviewers can reconstruct the exact before…after range; add environment variables like PRE_COMMIT_SHA: ${{ github.event.before }} and COMPARE_RANGE: ${{ github.event.before }}..${{ github.sha }} alongside COMMIT_SHA, and use those variables when building the issue body or links in the job that creates the audit issue.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/bypass-audit.yml:
- Around line 104-108: The current identity check using ACTOR with the wildcard
'"$ACTOR" == *"[bot]"*' and the exact '"$ACTOR" == "github-actions"' is too
broad; replace it with an explicit allowlist of trusted automation actor names
(e.g., canonical GitHub Actions/service accounts and dependabot identifiers) or
normalize ACTOR by stripping a trailing "[bot]" suffix and then perform exact
comparisons against a small trusted set, and update the if condition that
currently evaluates ACTOR to use that allowlist/normalized comparison instead of
the wildcard match.
---
Outside diff comments:
In @.github/workflows/bypass-audit.yml:
- Around line 92-97: The audit issue body currently only records COMMIT_SHA and
COMMIT_MSG; update the workflow to also capture and persist the pre-push SHA
(github.event.before) and a full compare range string (e.g.,
"{github.event.before}..{github.sha}") so reviewers can reconstruct the exact
before…after range; add environment variables like PRE_COMMIT_SHA: ${{
github.event.before }} and COMPARE_RANGE: ${{ github.event.before }}..${{
github.sha }} alongside COMMIT_SHA, and use those variables when building the
issue body or links in the job that creates the audit issue.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 33c58693-eb4c-45c4-9fdc-f9224db4d1fa
📒 Files selected for processing (1)
.github/workflows/bypass-audit.yml
A multi-commit direct push whose HEAD is PR-associated (e.g. a re-pushed already-merged commit) could hide earlier unaudited commits. Loop over github.event.commits and check each commit's PR association, filing one issue per un-PR'd commit and failing the run on any indeterminate lookup. GitHub caps the push payload commit list at 20; the remainder is an accepted residual (the org audit log records every commit). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
Replace per-commit issue creation with a single summary issue listing all bypassing commits in a table — avoids GitHub's content-creation rate limit on a multi-commit bypass and never false-positives a large legitimate merge. Commit subjects are sanitized and inline-code-wrapped (no Markdown injection). Extract the first line via bash parameter expansion, not head, so the GitHub `-eo pipefail` shell can't SIGPIPE-abort on a huge message. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
The audit-log API requires GitHub Enterprise Cloud; non-Enterprise orgs use the audit-log export. Drop the contested web-UI claim. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c4157f2539
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| COMMIT_MSG: ${{ github.event.head_commit.message }} | ||
| RUN_ID: ${{ github.run_id }} | ||
| HEAD_SHA: ${{ github.sha }} | ||
| COMMITS_JSON: ${{ toJSON(github.event.commits) }} |
There was a problem hiding this comment.
Read the push payload from the event file
When a push contains many commits or large commit messages, toJSON(github.event.commits) can exceed the OS per-environment-string limit before the step's shell starts, so the audit never reaches the new MAX_AUDIT handling or creates the summary issue. Since this workflow now depends on the full commit list, read commits from $GITHUB_EVENT_PATH inside the script instead of serializing the whole array through env.
Useful? React with 👍 / 👎.
`/commits/{sha}/pulls` also returns PRs that merely contain the commit
(open PRs, PRs targeting other branches), so a direct-pushed commit that
also lives on an unmerged branch read as "no bypass" — an undetected
bypass. Filter to PRs with merged_at != null AND base.ref == main
(matches seatbelt's sweep design).
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
GitHub's commit->PR association marks a SHA as belonging to a merged PR even for the original commits of a squash-merged PR (which never landed on main). A direct push of one of those exact SHAs is not flagged — an accepted, irreducible residual of the association API; the org audit log records the actual push. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
1e932a3 to
9d00994
Compare
toJSON(github.event.commits) materialized the whole push payload (up to 2048 commits, each with message + file lists + URLs) into a single env var. With a large push that can exceed the runner's env/ARG_MAX limit (~2 MB), making the audit step fail to exec before any logic runs — silently suppressing the very bypass this workflow exists to detect. Read commit ids and messages from $GITHUB_EVENT_PATH with jq instead (file data, never shell-interpolated), and fail the run when the payload is unreadable, not JSON, or .commits is not an array (indeterminate), so a multi-commit bypass cannot slip through a silent HEAD-only fallback. A valid but empty commit list still legitimately falls back to HEAD. Bumps the helmet-pipeline stamp v1.21.1 -> v1.21.2. Flagged independently by codex and cubic on the converged fleet PRs. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
4829f5a to
4aed129
Compare
# [1.56.0](v1.55.0...v1.56.0) (2026-06-05) ### Features * **ci:** adopt canonical no-dedup bypass-audit standard ([#181](#181)) ([ba03bec](ba03bec))
Converges busdriver's
admin-bypassaudit onto the canonical no-dedup standard (helmet ADR-0001, pipelinev1.21.1), superseding the closed dedup PR #178.What changes
github.actor(unforgeable); no commit-message[skip ci]/chore(release)skip (attacker-forgeable).gh apiPR lookup fails the run (durable red-X) rather than emitting a false-positive issue or silently passing.contents: readadded for/commits/{sha}/pullson private repos; audit-trail comments made org/user-owned accurate.# helmet-pipeline: v1.21.1for drift detection.Validation
litmus PASS — 5 codex iterations hardened the canonical template itself (this PR carries those fixes; a helmet backport follows).
🤖 Generated with Claude Code
Summary by cubic
Adopts the canonical no-dedup admin-bypass audit: audits every commit in a push, flags those not merged via a PR into
main, and files one summary issue. Adds fail-closed behavior and hardens the workflow (helmet-pipeline: v1.21.2).Refactors
github.actor(no message-based skips).$GITHUB_EVENT_PATH(fallbackgithub.sha); cap at 256, fail the run if payload is indeterminate or push exceeds cap; continue auditing remaining commits but fail the run on any indeterminate lookup or issue-creation failure.admin-bypasslabel exists with unlabeled fallback; sanitize commit subjects and render as inline code; separategh apistderr from JSON; make pipes pipefail-safe.contents: read, timeout 10m, set concurrency tobypass-audit-${{ github.sha }}, stamphelmet-pipeline: v1.21.2; clarify org audit-log access (Enterprise API or export) and note the squash-merge original-commit residual and CI-skip residual for user-owned repos.Bug Fixes
mainas non-bypass to avoid missing direct pushes that also appear in open/other-branch PRs.Written for commit 4aed129. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
Chores