Skip to content

chore(release): require audited dispatch SHA - #1559

Merged
Ingwannu merged 5 commits into
devfrom
hardening/release-expected-sha
Aug 13, 2026
Merged

chore(release): require audited dispatch SHA#1559
Ingwannu merged 5 commits into
devfrom
hardening/release-expected-sha

Conversation

@Wibias

@Wibias Wibias commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • require expected-sha for every manual Release workflow dispatch
  • fail closed if the supplied SHA is missing, malformed, or no longer matches the selected release ref
  • validate manual release dispatches against trusted guard code loaded from the repository default branch
  • allow releases only from main and preview
  • run dispatch validation in a separate read-only job before the privileged publish job can start
  • scope GitHub write and OIDC permissions to the publish job instead of granting them workflow-wide
  • add focused tests for the release dispatch guard

Why

The Release workflow is designed to publish an explicitly reviewed and audited commit, but the previous workflow still had two trust gaps.

First, expected-sha was optional. A manually dispatched release without it could continue by publishing whatever commit the selected branch currently pointed at.

Second, branch/ref validation happened only after the selected dispatch ref had already been checked out and repository code had begun executing. Since workflow_dispatch can be started against a selected branch, that meant release-ref code could run before the workflow had established that the dispatch came from an approved release branch.

This change makes the release path fail closed.

A new validate-dispatch job:

  • has only contents: read
  • checks out the dispatch guard explicitly from the repository default branch
  • requires the event to be workflow_dispatch
  • permits only refs/heads/main and refs/heads/preview
  • requires a full 40-character expected-sha
  • requires GITHUB_SHA to exactly match that audited SHA

Only after that validation succeeds can the publish job start.

The write-capable permissions required for GitHub release creation and npm Trusted Publishing are now scoped specifically to publish, rather than being granted to every job in the workflow.

Impact

Normal releases through bun scripts/release.ts remain compatible because the helper already:

  • runs only from main or preview
  • waits for CI before dispatch
  • verifies the live remote branch head before dispatch
  • supplies expected-sha=${releaseSha}

Intentional behavior changes:

  • manual releases without expected-sha are rejected
  • short or malformed SHAs are rejected
  • dispatches from branches other than main or preview are rejected
  • the privileged publish job cannot begin unless trusted dispatch validation succeeds

No npm publishing semantics, release channel mapping, or main/preview release support are removed.

Validation

Added focused tests covering:

  • valid main dispatch
  • valid preview dispatch
  • non-workflow_dispatch events
  • unapproved refs such as dev
  • missing expected-sha
  • non-full commit SHAs
  • branch movement after audit

CodeRabbit's two security findings covering dispatch trust ordering and trusted guard invocation are now resolved.

Review

Ready for review.

@lidge-jun @Ingwannu

Changed expected-sha input to be required for release.
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Wibias, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 4 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a156dbd4-6139-4a56-b030-d3f964f228a6

📥 Commits

Reviewing files that changed from the base of the PR and between d4bfae5 and d373694.

📒 Files selected for processing (1)
  • tests/ci-workflows.test.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f71b60da-6bdb-460d-94d4-5cf414d082fb

📥 Commits

Reviewing files that changed from the base of the PR and between 3e2733e and d4bfae5.

📒 Files selected for processing (2)
  • .github/scripts/release-dispatch-guard.test.cjs
  • .github/workflows/release.yml

📝 Walkthrough

Walkthrough

The release workflow now requires expected-sha. A new validation job checks the dispatch event, ref, and commit SHA before the publish job runs.

Changes

Release SHA Verification

Layer / File(s) Summary
Validate release dispatch parameters
.github/scripts/release-dispatch-guard.cjs, .github/scripts/release-dispatch-guard.test.cjs
validateReleaseDispatch accepts only workflow_dispatch events from main or preview. It requires a full 40-character SHA and compares it with the actual commit SHA. Tests cover valid and invalid inputs.
Gate publishing on dispatch validation
.github/workflows/release.yml
The expected-sha input is required at line 29. The read-only validate-dispatch job validates the dispatch before publish runs. Missing expected-sha now reports an error and stops the workflow at lines 92–93.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to d4bfa

The release workflow now requires an explicit audited commit and fails closed when it is missing; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

  • lidge-jun/opencodex#899: Both changes strengthen release validation in .github/workflows/release.yml, but they add different checks.

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: requiring an audited dispatch SHA for releases.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hardening/release-expected-sha

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

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/release.yml:
- Around line 57-58: Move trusted dispatch-ref validation ahead of checkout and
any commands that execute release-ref code, using scripts from the trusted
default branch to validate the requested ref. Preserve the existing main and
preview allowlist, then check out the approved ref and retain expected-sha
validation to bind it to the audited commit.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8d348efa-174c-4027-baae-c179f236f889

📥 Commits

Reviewing files that changed from the base of the PR and between cfc61c1 and 5e5d3fb.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Comment thread .github/workflows/release.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/scripts/release-dispatch-guard.cjs:
- Around line 8-38: Invoke validateReleaseDispatch from trusted code in the
release workflow before any GitHub or npm release operations, using the
repository default branch revision rather than the dispatch-selected ref. Pass
the workflow event, ref, expected SHA, and checked-out actual SHA to the guard,
fail immediately on a validation message, and retain support for
refs/heads/preview.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a8a80e4f-576d-40ce-9aa6-ae7e89ba8176

📥 Commits

Reviewing files that changed from the base of the PR and between 5e5d3fb and 3e2733e.

📒 Files selected for processing (1)
  • .github/scripts/release-dispatch-guard.cjs

Comment thread .github/scripts/release-dispatch-guard.cjs

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review completed on exact head d373694b1cd8c1660ca4793d444035f457222243. The release gate is loaded from the trusted default branch before release-ref code runs, dispatch is limited to main/preview, expected-sha is required as a full SHA and compared to GITHUB_SHA, workflow-level permissions are empty, and write/OIDC permissions exist only on the gated publish job. The actual PR diff is four files and exact-head CI is green. Approved from the release-integrity boundary.

@Ingwannu
Ingwannu merged commit 998d367 into dev Aug 13, 2026
22 checks passed
@Ingwannu
Ingwannu deleted the hardening/release-expected-sha branch August 13, 2026 02:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants