Skip to content

Use caller-scoped job token for release assets - #167

Draft
gontzess wants to merge 2 commits into
steve.gontzes/gf16-action-allowlistfrom
steve.gontzes/sh13-release-token
Draft

gontzess wants to merge 2 commits into
steve.gontzes/gf16-action-allowlistfrom
steve.gontzes/sh13-release-token

Conversation

@gontzess

@gontzess gontzess commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Stack: stacked on #166; merges after it.

Why

Stop giving GoReleaser an organization-wide release token when it only needs the caller repository's job token.

What

  • Switch all four GoReleaser environments to github.token.
  • Grant contents: write only to goreleaser-binaries, the sole job whose GoReleaser configuration enables GitHub Release creation/upload. Windows, Docker OCI and Lambda configurations disable GitHub Release publication and keep contents: read.
  • Keep workflow-wide permissions empty and existing metadata reads on the job token.
  • Preserve the Homebrew tap step as the sole legacy-token consumer. Its fine-grained tap-only replacement remains an administrator handoff; no secrets are created or rotated here.
  • Update the existing bootstrap permission contract and add token-boundary fixtures with adverse controls.

Caller inventory and rollout dependency

DO NOT roll out before caller permissions are inventoried and explicitly granted where needed. A callee cannot elevate a read-only caller grant. The public Go caller template and available rendered examples declare no explicit permissions block, so effective fleet defaults are unverified, not known-broken. The required caller release-job grant is contents: write plus id-token: write for the existing signing/publishing path, retaining actions: read and checks: read for workflow-run and failure-annotation reads. Do not broaden unrelated caller jobs. Releases GoReleaser creates with the job token do not trigger caller on: release workflows; inventory callers for such workflows as part of the rollout.

Named rollout dependency: https://github.com/ConductorOne/baton-admin/pull/1016 explicitly grants the caller release job contents: write, id-token: write, actions: read and checks: read. Render/update callers from that change before promoting this token switch. This PR intentionally does not modify caller repositories.

Evidence

  • tested at 49fe773; release.yaml remains byte-identical after restacking onto stripped Pin privileged release actions and document custody #166 head 6583b65.
  • make test-scripts: PASS after updating the deliberately changed bootstrap permission assertion (native PowerShell fixture skipped because PowerShell is unavailable).
  • make workflow-validate: PASS.
  • git diff --check: PASS.
  • Five token fixture tests cover the four GoReleaser steps, publication-disabled configurations, the single tap residual, and negative controls for read-only publishing, broader grants and legacy-token regression.
  • The first full script run correctly failed the old binaries contents: read contract; the assertion now expects write only for that publisher and the complete suite was rerun.

Limits and handoff

Draft only. Live canary asset upload, Homebrew delivery and the deliberately read-only upload negative control were not run. Complete them after the caller grant prerequisite. contents: write is repository-scoped but not asset-only: it can modify contents and tags while the job token is valid.

The deferred tap leg needs a short-lived HOMEBREW_TAP_TOKEN scoped to conductorone/homebrew-baton with contents: write only, plus administrator-owned rotation. Until then, the secret declaration and one Publish Homebrew formula use of RELENG_GITHUB_TOKEN are the only residuals.

Live evidence (2026-10-22)

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit a69c0468a41d

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - .claude/skills/ci-review.md was not found at trusted base ad85b5b02764.
Review mode: full
View review run

Review Summary

This PR moves the four GoReleaser steps (binaries, windows, docker-oci, lambda) in release.yaml from the org-wide RELENG_GITHUB_TOKEN to github.token. Only goreleaser-binaries gets contents: write. RELENG_GITHUB_TOKEN is still used by the Publish Homebrew formula step, which is the only step that writes to the tap. The PR also adds scripts/test-release-tokens.py, wires it into make test-scripts, updates the bootstrap permission assertion, and documents the token boundary.

I scanned the full PR diff for security and correctness issues and checked the claims against the code:

  • Every checkout step in the workflow sets persist-credentials: false, including both checkouts in the write-scoped job (release.yaml:414,432). The write token therefore never lands in .git/config where later caller-controlled build steps could read it.
  • The binaries template's brews entry has skip_upload: "true", so GoReleaser never needs tap access.
  • The windows, docker-oci and docker-lambda templates set release.disable: true and changelog.disable: true, so contents: read is enough for them.
  • Workflow-level permissions: {} is unchanged.

No repo-local criteria loaded, so the base criteria were applied. There were no prior findings to audit.

Coverage gap: whether the caller fleet actually grants these permissions can't be checked from this repo. The PR also says no live canary was run.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • New (medium confidence) .github/workflows/release.yaml:400: The job-level request for contents: write will make GitHub reject the whole called workflow at startup for any caller that grants only contents: read, such as one relying on a read-only org default. That affects every caller tracking this ref as soon as it merges. The rollout dependency is written down in the PR body but nothing enforces it. Gate the merge on the companion caller-permission PR, or release this as a breaking change so callers that pin a ref opt in.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: The goreleaser-binaries job now requests `contents: write`. Any caller whose release job grants only `contents: read` (explicitly or via a read-only org default) will have the entire reusable workflow rejected at startup, not just this job. Do not merge until the companion caller-permission change is deployed, or release this under a new major tag/ref so pinned callers opt in. Add a note to docs/release-workflow.md that callers must update their permissions before moving to this ref.

GOSUMDB: sum.golang.org
permissions:
contents: read
contents: write # Create/upload the caller repository's GitHub release assets.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Suggestion (medium confidence): If a caller grants only contents: read, for example through a read-only org default, GitHub rejects the whole called workflow at startup. The error is "nested job is requesting 'contents: write'", so this is not limited to the binaries job, and it affects every caller that tracks this ref as soon as it merges. The PR body covers this, but the guard is only prose. Consider merging only after the caller-template PR lands, or tagging this as a breaking release so callers that pin a ref opt in.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 95fa7909dbf4

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - .claude/skills/ci-review.md was not found at trusted base ad85b5b02764.
Review mode: full
View review run

Review Summary

This PR moves the four GoReleaser steps (binaries, windows, docker-oci, lambda) in release.yaml from the org-wide RELENG_GITHUB_TOKEN to github.token. Only goreleaser-binaries gets contents: write. RELENG_GITHUB_TOKEN is still used by the Publish Homebrew formula step, which is the only step that writes to the tap. The PR also adds scripts/test-release-tokens.py, wires it into make test-scripts, updates the bootstrap permission assertion, and documents the token boundary.

I scanned the full PR diff for security and correctness issues and checked the claims against the code:

  • Every checkout step in the workflow sets persist-credentials: false, including both checkouts in the write-scoped job (release.yaml:414,432). The write token therefore never lands in .git/config where later caller-controlled build steps could read it.
  • The binaries template's brews entry has skip_upload: "true", so GoReleaser never needs tap access.
  • The windows, docker-oci and docker-lambda templates set release.disable: true and changelog.disable: true, so contents: read is enough for them.
  • Workflow-level permissions: {} is unchanged.

No repo-local criteria loaded, so the base criteria were applied. There were no prior findings to audit.

Coverage gap: whether the caller fleet actually grants these permissions can't be checked from this repo. The PR also says no live canary was run.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • New (medium confidence) .github/workflows/release.yaml:400: The job-level request for contents: write will make GitHub reject the whole called workflow at startup for any caller that grants only contents: read, such as one relying on a read-only org default. That affects every caller tracking this ref as soon as it merges. The rollout dependency is written down in the PR body but nothing enforces it. Gate the merge on the companion caller-permission PR, or release this as a breaking change so callers that pin a ref opt in.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: The goreleaser-binaries job now requests `contents: write`. Any caller whose release job grants only `contents: read` (explicitly or via a read-only org default) will have the entire reusable workflow rejected at startup, not just this job. Do not merge until the companion caller-permission change is deployed, or release this under a new major tag/ref so pinned callers opt in. Add a note to docs/release-workflow.md that callers must update their permissions before moving to this ref.

Reviewed commit: a69c0468a41d

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess changed the base branch from main to steve.gontzes/gf16-action-allowlist October 22, 2026 14:59
@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from a69c046 to 86bc9b9 Compare October 22, 2026 14:59
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 86bc9b900f47

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 2 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps in release.yaml now get GITHUB_TOKEN from ${{ github.token }} instead of the org-wide RELENG_GITHUB_TOKEN. Only goreleaser-binaries gets contents: write. RELENG_GITHUB_TOKEN is now used only by the Homebrew tap step. The PR also adds scripts/test-release-tokens.py (with negative controls), updates the bootstrap permission assertion and documents what callers must grant. I scanned the full diff for security and correctness and checked the GoReleaser templates. The Windows, docker-oci and docker-lambda templates set release.disable: true and push only to ECR, not GHCR, so contents: read is enough for them. The binaries brews entry is skip_upload, so GoReleaser never needs tap access. Checksums go to S3, not the GitHub Release. Overall this narrows privilege: caller-controlled build steps no longer see an org-wide token. No repo-local criteria loaded, so only the base criteria were applied.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: The reusable workflow now asks for contents: write. GitHub refuses to start the whole called workflow, not just this job, for any caller whose grant is contents: read, such as a read-only org default. The new "Release and Tap Token Boundaries" section in docs/release-workflow.md now lists the caller grants, and the PR body names baton-admin#1016 as a prerequisite. Nothing enforces that order, though, so callers tracking this ref break on merge if they haven't updated. The existing open thread covers this.
  • New (low-medium confidence) .github/workflows/release.yaml:515: For plain tag pushes (prerelease=absent in preflight, lines 352-354), GoReleaser now creates the GitHub Release with github.token. Events triggered by GITHUB_TOKEN do not start other workflows, so a caller on: release workflow that used to fire on PAT-created releases will silently stop. This belongs in the caller inventory.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`, so GitHub rejects the entire reusable workflow at startup for callers that grant only `contents: read`. Before merging, deploy the caller-permission change (baton-admin#1016) to all callers tracking this ref, or publish this under a new ref/tag so callers opt in.
- Around line 512-515: When no GitHub Release exists for the tag, GoReleaser creates it with `github.token`, and `release:` events from GITHUB_TOKEN do not trigger caller workflows. Inventory callers for `on: release` workflows, and document this change in docs/release-workflow.md under "Release and Tap Token Boundaries" (or have callers create releases up front).

run: goreleaser release --clean --config ../_workflows/_generated/.goreleaser.binaries.yaml
env:
GITHUB_TOKEN: ${{ secrets.RELENG_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Suggestion (low-medium confidence): For plain tag pushes, release-preflight reports prerelease=absent and GoReleaser creates the GitHub Release itself. A release created with github.token does not fire release: events, so any caller workflow listening for release: [published|created] silently stops running (it did fire when the release was made with the PAT). Please add this to the caller inventory and docs, or check that no caller depends on it.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 2828b7b0d896

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 2 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps in release.yaml now get GITHUB_TOKEN from ${{ github.token }} instead of the org-wide RELENG_GITHUB_TOKEN. Only goreleaser-binaries gets contents: write. RELENG_GITHUB_TOKEN is now used only by the Homebrew tap step. The PR also adds scripts/test-release-tokens.py (with negative controls), updates the bootstrap permission assertion and documents what callers must grant. I scanned the full diff for security and correctness and checked the GoReleaser templates. The Windows, docker-oci and docker-lambda templates set release.disable: true and push only to ECR, not GHCR, so contents: read is enough for them. The binaries brews entry is skip_upload, so GoReleaser never needs tap access. Checksums go to S3, not the GitHub Release. Overall this narrows privilege: caller-controlled build steps no longer see an org-wide token. No repo-local criteria loaded, so only the base criteria were applied.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: The reusable workflow now asks for contents: write. GitHub refuses to start the whole called workflow, not just this job, for any caller whose grant is contents: read, such as a read-only org default. The new "Release and Tap Token Boundaries" section in docs/release-workflow.md now lists the caller grants, and the PR body names baton-admin#1016 as a prerequisite. Nothing enforces that order, though, so callers tracking this ref break on merge if they haven't updated. The existing open thread covers this.
  • New (low-medium confidence) .github/workflows/release.yaml:515: For plain tag pushes (prerelease=absent in preflight, lines 352-354), GoReleaser now creates the GitHub Release with github.token. Events triggered by GITHUB_TOKEN do not start other workflows, so a caller on: release workflow that used to fire on PAT-created releases will silently stop. This belongs in the caller inventory.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`, so GitHub rejects the entire reusable workflow at startup for callers that grant only `contents: read`. Before merging, deploy the caller-permission change (baton-admin#1016) to all callers tracking this ref, or publish this under a new ref/tag so callers opt in.
- Around line 512-515: When no GitHub Release exists for the tag, GoReleaser creates it with `github.token`, and `release:` events from GITHUB_TOKEN do not trigger caller workflows. Inventory callers for `on: release` workflows, and document this change in docs/release-workflow.md under "Release and Tap Token Boundaries" (or have callers create releases up front).

Reviewed commit: 86bc9b900f47

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 86bc9b9 to 2828b7b Compare October 22, 2026 15:34
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 2828b7b0d896

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four goreleaser release steps now get GITHUB_TOKEN: ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. It is the only job whose template leaves GitHub Release publication on. The windows, docker-oci and docker-lambda templates all set release.disable: true. RELENG_GITHUB_TOKEN stays in exactly one place, the Publish Homebrew formula step (release.yaml:527). The PR also adds scripts/test-release-tokens.py with negative controls, updates the bootstrap permission assertion, and documents the token boundary, the caller grants required for rollout, and the fact that releases created with the job token don't trigger on: release.

I scanned the full PR diff for security and correctness and checked it against the surrounding job definitions and GoReleaser templates. These parts are sound:

  • Workflow-level permissions: {} is unchanged.
  • Both checkouts in the write-scoped job use persist-credentials: false (release.yaml:414,432).
  • The brews entry uses skip_upload: "true", so GoReleaser doesn't need access to the tap.
  • The new test relies on kislyuk's yq, which ci.yaml:71-74 installs.

No repo-local criteria loaded, so I applied only the base criteria.

Security Issues

None found. Swapping the organization-wide PAT for the caller-scoped job token is a net reduction in privilege. The binaries job's job token now has contents: write, so any step in that job can modify the caller repository's contents and tags. The PR body and docs say this openly, and every third-party action in the job is pinned to a SHA.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: The reusable workflow now asks for contents: write. GitHub refuses to start the whole called workflow, not just this job, for any caller whose grant is contents: read, such as a read-only org default. The docs (docs/release-workflow.md, "Release and Tap Token Boundaries") and the PR body name baton-admin#1016 as a prerequisite, but nothing enforces that order. Callers tracking this ref break on merge if they haven't updated. The existing open thread covers this.

Resolved prior findings

  • Fixed (prior summary, release.yaml:515, releases created with GITHUB_TOKEN don't trigger caller on: release workflows): the docs now cover this in docs/release-workflow.md under "Release and Tap Token Boundaries" ("Releases GoReleaser creates with the job token do not trigger caller on: release workflows; inventory callers for such workflows as part of the rollout"), and the PR body adds it to the rollout inventory.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`, so GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read` (explicitly or via a read-only org default). Before merging, deploy the caller-permission change (baton-admin#1016) to every caller tracking this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 95fa7909dbf4

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four goreleaser release steps now get GITHUB_TOKEN: ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. It is the only job whose template leaves GitHub Release publication on. The windows, docker-oci and docker-lambda templates all set release.disable: true. RELENG_GITHUB_TOKEN stays in exactly one place, the Publish Homebrew formula step (release.yaml:527). The PR also adds scripts/test-release-tokens.py with negative controls, updates the bootstrap permission assertion, and documents the token boundary, the caller grants required for rollout, and the fact that releases created with the job token don't trigger on: release.

I scanned the full PR diff for security and correctness and checked it against the surrounding job definitions and GoReleaser templates. These parts are sound:

  • Workflow-level permissions: {} is unchanged.
  • Both checkouts in the write-scoped job use persist-credentials: false (release.yaml:414,432).
  • The brews entry uses skip_upload: "true", so GoReleaser doesn't need access to the tap.
  • The new test relies on kislyuk's yq, which ci.yaml:71-74 installs.

No repo-local criteria loaded, so I applied only the base criteria.

Security Issues

None found. Swapping the organization-wide PAT for the caller-scoped job token is a net reduction in privilege. The binaries job's job token now has contents: write, so any step in that job can modify the caller repository's contents and tags. The PR body and docs say this openly, and every third-party action in the job is pinned to a SHA.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: The reusable workflow now asks for contents: write. GitHub refuses to start the whole called workflow, not just this job, for any caller whose grant is contents: read, such as a read-only org default. The docs (docs/release-workflow.md, "Release and Tap Token Boundaries") and the PR body name baton-admin#1016 as a prerequisite, but nothing enforces that order. Callers tracking this ref break on merge if they haven't updated. The existing open thread covers this.

Resolved prior findings

  • Fixed (prior summary, release.yaml:515, releases created with GITHUB_TOKEN don't trigger caller on: release workflows): the docs now cover this in docs/release-workflow.md under "Release and Tap Token Boundaries" ("Releases GoReleaser creates with the job token do not trigger caller on: release workflows; inventory callers for such workflows as part of the rollout"), and the PR body adds it to the rollout inventory.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`, so GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read` (explicitly or via a read-only org default). Before merging, deploy the caller-permission change (baton-admin#1016) to every caller tracking this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions.

Reviewed commit: 2828b7b0d896

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 2828b7b to 95fa790 Compare October 22, 2026 16:37
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 95fa7909dbf4

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps in release.yaml (binaries, windows, docker-oci, docker-lambda) now use ${{ github.token }} instead of RELENG_GITHUB_TOKEN. goreleaser-binaries is now the only job with contents: write. RELENG_GITHUB_TOKEN is still used in exactly one place, the Publish Homebrew formula step (release.yaml:527). The PR also adds a docs section on token boundaries, a new offline fixture test (scripts/test-release-tokens.py, wired into make test-scripts), and an updated assertion in test-tool-integrity.py. I scanned the full PR diff for security and correctness problems. No repo-local criteria loaded, so I applied only the base criteria.

What I checked:

  • Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • Windows artifacts go to S3, not to a GitHub release.
  • After GoReleaser, the binaries job's only GitHub API call is a release-metadata read with the job token (release.yaml:658).
  • Workflow-level permissions: {} is unchanged.
  • Nothing in the workflow edits a GitHub release with a read-only token.
  • The new test covers wrong token wiring and broader permission grants, and includes negative controls.

Coverage gap: I did not run a live release. Asset upload with the job token and the Homebrew tap write are still untested. The PR description says the same.

Security Issues

None found. The change reduces privilege: the org-wide token moves out of GoReleaser, and the new write grant is limited to the caller repository and one job.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the entire called workflow for any caller whose grant is only contents: read, for example a caller with no explicit permissions under a read-only org default. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order. Callers tracking this ref break on merge if they haven't updated. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps in release.yaml (binaries, windows, docker-oci, docker-lambda) now use ${{ github.token }} instead of RELENG_GITHUB_TOKEN. goreleaser-binaries is now the only job with contents: write. RELENG_GITHUB_TOKEN is still used in exactly one place, the Publish Homebrew formula step (release.yaml:527). The PR also adds a docs section on token boundaries, a new offline fixture test (scripts/test-release-tokens.py, wired into make test-scripts), and an updated assertion in test-tool-integrity.py. I scanned the full PR diff for security and correctness problems. No repo-local criteria loaded, so I applied only the base criteria.

What I checked:

  • Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • Windows artifacts go to S3, not to a GitHub release.
  • After GoReleaser, the binaries job's only GitHub API call is a release-metadata read with the job token (release.yaml:658).
  • Workflow-level permissions: {} is unchanged.
  • Nothing in the workflow edits a GitHub release with a read-only token.
  • The new test covers wrong token wiring and broader permission grants, and includes negative controls.

Coverage gap: I did not run a live release. Asset upload with the job token and the Homebrew tap write are still untested. The PR description says the same.

Security Issues

None found. The change reduces privilege: the org-wide token moves out of GoReleaser, and the new write grant is limited to the caller repository and one job.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the entire called workflow for any caller whose grant is only contents: read, for example a caller with no explicit permissions under a read-only org default. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order. Callers tracking this ref break on merge if they haven't updated. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 95fa7909dbf4

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess added this pull request to stack #170 October 22, 2026 19:00
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 95fa7909dbf4

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps now get ${{ github.token }} in place of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries moves from contents: read to contents: write, and workflow-level permissions: {} does not change. The legacy token is now used in exactly one place, the Publish Homebrew formula step. The PR also adds a rollout section to docs/release-workflow.md, a new offline test (scripts/test-release-tokens.py, wired into make test-scripts), and an updated permission assertion in test-tool-integrity.py.

I scanned the full PR diff for security and correctness problems, and read the whole binaries job to see where the write-scoped token can reach:

  • Both checkouts set persist-credentials: false.
  • The token is exposed only through the GoReleaser env and the read-only gh api metadata call.
  • Before this PR, the same GoReleaser step held the organization-wide token, so this change shrinks what that step can touch.

Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates disable release publication, so contents: read is enough for those jobs. No repo-local criteria loaded because the base branch is not main, so I applied the base criteria only. I did not run live release, upload or Homebrew tests, and the PR says the same.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write.
    • GitHub refuses to start the whole called workflow for any caller whose grant is only contents: read. That includes a caller with no explicit permissions block under a read-only org default.
    • The PR body and the new "Release and Tap Token Boundaries" doc section name baton-admin#1016 as a prerequisite, but nothing enforces that order.
    • Callers that track this ref and haven't updated will break when this merges.
    • An open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit fc53831c4958

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps now get ${{ github.token }} in place of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries moves from contents: read to contents: write, and workflow-level permissions: {} does not change. The legacy token is now used in exactly one place, the Publish Homebrew formula step. The PR also adds a rollout section to docs/release-workflow.md, a new offline test (scripts/test-release-tokens.py, wired into make test-scripts), and an updated permission assertion in test-tool-integrity.py.

I scanned the full PR diff for security and correctness problems, and read the whole binaries job to see where the write-scoped token can reach:

  • Both checkouts set persist-credentials: false.
  • The token is exposed only through the GoReleaser env and the read-only gh api metadata call.
  • Before this PR, the same GoReleaser step held the organization-wide token, so this change shrinks what that step can touch.

Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates disable release publication, so contents: read is enough for those jobs. No repo-local criteria loaded because the base branch is not main, so I applied the base criteria only. I did not run live release, upload or Homebrew tests, and the PR says the same.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write.
    • GitHub refuses to start the whole called workflow for any caller whose grant is only contents: read. That includes a caller with no explicit permissions block under a read-only org default.
    • The PR body and the new "Release and Tap Token Boundaries" doc section name baton-admin#1016 as a prerequisite, but nothing enforces that order.
    • Callers that track this ref and haven't updated will break when this merges.
    • An open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 95fa7909dbf4

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 95fa790 to fc53831 Compare October 22, 2026 19:09
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit fc53831c4958

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

All four goreleaser release steps in .github/workflows/release.yaml now get GITHUB_TOKEN from ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. In a reusable workflow, that token belongs to the caller repository. The PR raises contents to write only on goreleaser-binaries. That matches the templates: only the binaries config publishes a GitHub Release (no release.disable), while the windows, docker-oci and docker-lambda configs set release.disable: true. Workflow-wide permissions: {} is unchanged. The only remaining use of RELENG_GITHUB_TOKEN is the Publish Homebrew formula step. Every job declares a permissions block, so the new scripts/test-release-tokens.py will not hit a KeyError. Its negative controls exercise each regression direction, and the bootstrap assertion in test-tool-integrity.py was updated to match. I scanned the full PR diff for security and correctness issues. No repo-local criteria loaded, so only the base criteria were applied.

Security Issues

None found. The PR narrows credential scope: an org-wide PAT is replaced by the caller-scoped job token that expires with the job. Neither checkout persists credentials. The binaries job's other github.token use is a read-only gh api release lookup (release.yaml:658).

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller that grants only contents: read, either explicitly or through a read-only org default with no permissions block. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order, so callers tracking this ref break on merge if they haven't updated first. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 49fe77310491

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

All four goreleaser release steps in .github/workflows/release.yaml now get GITHUB_TOKEN from ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. In a reusable workflow, that token belongs to the caller repository. The PR raises contents to write only on goreleaser-binaries. That matches the templates: only the binaries config publishes a GitHub Release (no release.disable), while the windows, docker-oci and docker-lambda configs set release.disable: true. Workflow-wide permissions: {} is unchanged. The only remaining use of RELENG_GITHUB_TOKEN is the Publish Homebrew formula step. Every job declares a permissions block, so the new scripts/test-release-tokens.py will not hit a KeyError. Its negative controls exercise each regression direction, and the bootstrap assertion in test-tool-integrity.py was updated to match. I scanned the full PR diff for security and correctness issues. No repo-local criteria loaded, so only the base criteria were applied.

Security Issues

None found. The PR narrows credential scope: an org-wide PAT is replaced by the caller-scoped job token that expires with the job. Neither checkout persists credentials. The binaries job's other github.token use is a read-only gh api release lookup (release.yaml:658).

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller that grants only contents: read, either explicitly or through a read-only org default with no permissions block. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order, so callers tracking this ref break on merge if they haven't updated first. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: fc53831c4958

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from fc53831 to 49fe773 Compare October 22, 2026 20:45
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 49fe77310491

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps (binaries, windows, docker OCI, lambda) now get GITHUB_TOKEN from ${{ github.token }} instead of RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. The org token remains only in Publish Homebrew formula (release.yaml:527).

I scanned the full PR diff for security and correctness, and checked the code around it:

  • Every job in release.yaml declares job-level permissions, so test-release-tokens.py can index job["permissions"] safely.
  • Only .goreleaser-binaries-template.yaml.tmpl leaves release enabled. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • No other step uses RELENG_GITHUB_TOKEN (private module fetch or registry login), so nothing else depends on the old token.

No repo-local criteria loaded, so I applied the base criteria only.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write, so GitHub refuses to start the entire called workflow for any caller whose grant is read-only (explicitly or via a read-only org default). The PR body's negative run 39843978989 shows this happening. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order: callers tracking this ref break on merge until they update. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 573bbc48032d

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four GoReleaser steps (binaries, windows, docker OCI, lambda) now get GITHUB_TOKEN from ${{ github.token }} instead of RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. The org token remains only in Publish Homebrew formula (release.yaml:527).

I scanned the full PR diff for security and correctness, and checked the code around it:

  • Every job in release.yaml declares job-level permissions, so test-release-tokens.py can index job["permissions"] safely.
  • Only .goreleaser-binaries-template.yaml.tmpl leaves release enabled. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • No other step uses RELENG_GITHUB_TOKEN (private module fetch or registry login), so nothing else depends on the old token.

No repo-local criteria loaded, so I applied the base criteria only.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write, so GitHub refuses to start the entire called workflow for any caller whose grant is read-only (explicitly or via a read-only org default). The PR body's negative run 39843978989 shows this happening. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order: callers tracking this ref break on merge until they update. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 49fe77310491

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 49fe773 to 573bbc4 Compare October 22, 2026 20:55
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 573bbc48032d

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The PR switches the four GoReleaser invocations in release.yaml (binaries:515, windows:852, docker OCI:1178, lambda:1215) from RELENG_GITHUB_TOKEN to github.token. It raises only goreleaser-binaries to contents: write (line 400). Workflow-level permissions: {} (line 113) is unchanged, and Publish Homebrew formula (line 527) is the only step still using the legacy token. A new scripts/test-release-tokens.py checks these boundaries and includes negative controls, and the bootstrap assertion and docs are updated to match.

I scanned the full diff for security and correctness and checked the claims against the code:

  • Only .goreleaser-binaries-template.yaml.tmpl leaves release enabled. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • The brew formula uses skip_upload: "true", so GoReleaser never needs cross-repo access to the tap.
  • Every gh api metadata read already uses github.token with read scopes.

No repo-local criteria loaded (base is not main), so only the base criteria were applied. No coverage gaps.

Security Issues

None found. This change narrows credential exposure: the org-wide token no longer reaches GoReleaser.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller whose grant is read-only, whether set explicitly or through a read-only org default. The PR's negative run 39843978989 shows exactly this. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order, so callers tracking this ref break on merge until they update. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 4ac21665222e

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The PR switches the four GoReleaser invocations in release.yaml (binaries:515, windows:852, docker OCI:1178, lambda:1215) from RELENG_GITHUB_TOKEN to github.token. It raises only goreleaser-binaries to contents: write (line 400). Workflow-level permissions: {} (line 113) is unchanged, and Publish Homebrew formula (line 527) is the only step still using the legacy token. A new scripts/test-release-tokens.py checks these boundaries and includes negative controls, and the bootstrap assertion and docs are updated to match.

I scanned the full diff for security and correctness and checked the claims against the code:

  • Only .goreleaser-binaries-template.yaml.tmpl leaves release enabled. The windows, docker-oci and docker-lambda templates set release.disable: true, so contents: read is enough for those jobs.
  • The brew formula uses skip_upload: "true", so GoReleaser never needs cross-repo access to the tap.
  • Every gh api metadata read already uses github.token with read scopes.

No repo-local criteria loaded (base is not main), so only the base criteria were applied. No coverage gaps.

Security Issues

None found. This change narrows credential exposure: the org-wide token no longer reaches GoReleaser.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller whose grant is read-only, whether set explicitly or through a read-only org default. The PR's negative run 39843978989 shows exactly this. The PR body and docs/release-workflow.md ("Release and Tap Token Boundaries") name baton-admin#1016 as a prerequisite, but nothing enforces that order, so callers tracking this ref break on merge until they update. The existing open thread already covers this, so I did not post a duplicate inline comment.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 573bbc48032d

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 573bbc4 to 4ac2166 Compare October 22, 2026 21:00
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 4ac21665222e

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four goreleaser release steps (binaries, windows, docker, lambda) now get GITHUB_TOKEN: ${{ github.token }} instead of RELENG_GITHUB_TOKEN. Of those four jobs, only goreleaser-binaries is raised to contents: write, and workflow-level permissions: {} is unchanged. The legacy token is now used only by Publish Homebrew formula (release.yaml:527). A new offline test, scripts/test-release-tokens.py, enforces this wiring and is added to make test-scripts. Docs gain a "Release and Tap Token Boundaries" section.

I scanned the full PR diff for security and correctness and checked it against the templates and every job in release.yaml:

  • Only .goreleaser-binaries-template.yaml.tmpl publishes a GitHub Release. The windows, docker-oci and docker-lambda templates all set release.disable: true.
  • The brew block sets skip_upload: "true", so GoReleaser never writes to the tap repo.
  • All 10 jobs declare permissions, so the new test's job["permissions"] lookups cannot hit a missing key.

No repo-local criteria loaded (non-default base branch), so only the base criteria were applied.

Security Issues

None found. The change narrows credential exposure: the org-wide PAT is no longer passed to GoReleaser. The remaining contents: write is scoped to the caller repo and to a single job.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller whose grant is read-only, whether set explicitly or through a read-only org default. The PR's negative run 39843978989 shows exactly this. Rollout order (baton-admin#1016 first) is documented in the PR body and docs/release-workflow.md, but nothing enforces it. The open thread already covers this, so no duplicate inline comment was posted.

Resolved prior findings

  • Fixed: the thread at release.yaml:515 asked to document that releases created with github.token do not fire caller on: release workflows. docs/release-workflow.md ("Release and Tap Token Boundaries", rollout paragraph) now says this and requires callers to be inventoried for such workflows. The PR body says the same.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 99f172e938d2

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

The four goreleaser release steps (binaries, windows, docker, lambda) now get GITHUB_TOKEN: ${{ github.token }} instead of RELENG_GITHUB_TOKEN. Of those four jobs, only goreleaser-binaries is raised to contents: write, and workflow-level permissions: {} is unchanged. The legacy token is now used only by Publish Homebrew formula (release.yaml:527). A new offline test, scripts/test-release-tokens.py, enforces this wiring and is added to make test-scripts. Docs gain a "Release and Tap Token Boundaries" section.

I scanned the full PR diff for security and correctness and checked it against the templates and every job in release.yaml:

  • Only .goreleaser-binaries-template.yaml.tmpl publishes a GitHub Release. The windows, docker-oci and docker-lambda templates all set release.disable: true.
  • The brew block sets skip_upload: "true", so GoReleaser never writes to the tap repo.
  • All 10 jobs declare permissions, so the new test's job["permissions"] lookups cannot hit a missing key.

No repo-local criteria loaded (non-default base branch), so only the base criteria were applied.

Security Issues

None found. The change narrows credential exposure: the org-wide PAT is no longer passed to GoReleaser. The remaining contents: write is scoped to the caller repo and to a single job.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. GitHub refuses to start the whole called workflow for any caller whose grant is read-only, whether set explicitly or through a read-only org default. The PR's negative run 39843978989 shows exactly this. Rollout order (baton-admin#1016 first) is documented in the PR body and docs/release-workflow.md, but nothing enforces it. The open thread already covers this, so no duplicate inline comment was posted.

Resolved prior findings

  • Fixed: the thread at release.yaml:515 asked to document that releases created with github.token do not fire caller on: release workflows. docs/release-workflow.md ("Release and Tap Token Boundaries", rollout paragraph) now says this and requires callers to be inventoried for such workflows. The PR body says the same.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, whether explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref, or publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 4ac21665222e

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

gontzess and others added 2 commits October 22, 2026 21:25
Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
Co-authored-by: c1-squire-dev[bot] <c1-squire-dev[bot]@users.noreply.github.com>
@gontzess
gontzess force-pushed the steve.gontzes/sh13-release-token branch from 4ac2166 to 99f172e Compare October 22, 2026 21:26
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Superseded — see the current review report for commit 99f172e938d2

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

All four goreleaser release steps in release.yaml now use ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. The other jobs keep contents: read, and workflow-level permissions: {} is unchanged. RELENG_GITHUB_TOKEN is now used in one place only: the Publish Homebrew formula step (release.yaml:527). The PR also adds scripts/test-release-tokens.py with negative controls, updates the bootstrap permission assertion in test-tool-integrity.py, and documents the token boundaries and caller rollout prerequisites. The latest commit only adds docs: it records that caller on: release workflows are no longer triggered.

I scanned the full PR diff for security and correctness issues. The token wiring checks out:

  • Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates set release.disable: true.
  • Every gh api metadata read already uses GH_TOKEN: ${{ github.token }} (release.yaml:650, :1634, :1800).
  • No template pushes to ghcr or otherwise relies on the old token.

No repo-local criteria loaded, because the PR's base is not the default branch. Only the base criteria were applied.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. If a caller grants only read access, explicitly or through a read-only org default, GitHub refuses to start the whole called workflow. The PR's negative run 39843978989 shows exactly this. The PR body and docs/release-workflow.md say baton-admin#1016 must roll out first, but nothing enforces that order. The open thread already covers this, so I did not post a duplicate inline comment.

Resolved prior findings

  • Fixed: the thread at release.yaml:515 noted that releases created with github.token do not fire caller on: release workflows. docs/release-workflow.md ("Release and Tap Token Boundaries", rollout paragraph) now documents this and requires callers to be inventoried for such workflows.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, either explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref. Alternatively, publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

General PR Review: Use caller-scoped job token for release assets

Blocking Issues: 0 | Suggestions: 1 | Threads Resolved: 0
Criteria: Criteria status: none loaded - base ref steve.gontzes/gf16-action-allowlist is not the default branch main for .claude/skills/ci-review.md.
Review mode: full
View review run

Review Summary

All four goreleaser release steps in release.yaml now use ${{ github.token }} instead of secrets.RELENG_GITHUB_TOKEN. Only goreleaser-binaries is raised to contents: write. The other jobs keep contents: read, and workflow-level permissions: {} is unchanged. RELENG_GITHUB_TOKEN is now used in one place only: the Publish Homebrew formula step (release.yaml:527). The PR also adds scripts/test-release-tokens.py with negative controls, updates the bootstrap permission assertion in test-tool-integrity.py, and documents the token boundaries and caller rollout prerequisites. The latest commit only adds docs: it records that caller on: release workflows are no longer triggered.

I scanned the full PR diff for security and correctness issues. The token wiring checks out:

  • Only the binaries template publishes a GitHub Release. The windows, docker-oci and docker-lambda templates set release.disable: true.
  • Every gh api metadata read already uses GH_TOKEN: ${{ github.token }} (release.yaml:650, :1634, :1800).
  • No template pushes to ghcr or otherwise relies on the old token.

No repo-local criteria loaded, because the PR's base is not the default branch. Only the base criteria were applied.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

  • Prior — still present (medium confidence) .github/workflows/release.yaml:400: goreleaser-binaries now requests contents: write. If a caller grants only read access, explicitly or through a read-only org default, GitHub refuses to start the whole called workflow. The PR's negative run 39843978989 shows exactly this. The PR body and docs/release-workflow.md say baton-admin#1016 must roll out first, but nothing enforces that order. The open thread already covers this, so I did not post a duplicate inline comment.

Resolved prior findings

  • Fixed: the thread at release.yaml:515 noted that releases created with github.token do not fire caller on: release workflows. docs/release-workflow.md ("Release and Tap Token Boundaries", rollout paragraph) now documents this and requires callers to be inventoried for such workflows.
Prompt for AI agents
Verify each finding against the current code and only fix it if needed.

## Suggestions

In `.github/workflows/release.yaml`:
- Around line 399-401: goreleaser-binaries now requests `contents: write`. GitHub rejects the entire reusable workflow at startup for any caller that grants only `contents: read`, either explicitly or through a read-only org default. Before merging, deploy the caller-permission change (baton-admin#1016) to every caller that tracks this ref. Alternatively, publish this change under a new ref/tag so callers opt in after updating their release job's permissions (contents: write, id-token: write, actions: read, checks: read).

Reviewed commit: 99f172e938d2

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found — see the full review report

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