Skip to content

Push Homebrew tap via scoped deploy key instead of personal PAT - #102

Merged
ernestoongaro merged 1 commit into
mainfrom
harden/tap-deploy-key
Sep 21, 2026
Merged

ernestoongaro merged 1 commit into
mainfrom
harden/tap-deploy-key

Conversation

@ernestoongaro

@ernestoongaro ernestoongaro commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Why

The release job checks out exploreomni/homebrew-tap using secrets.HOMEBREW_TAP_GITHUB_TOKEN.

That secret is a classic PAT on a personal account, created 2026-04-14 and never rotated since. The git config user.name "github-actions[bot]" in the publish step is cosmetic — it only labels the commit author. Every PushEvent on the tap reports actor=ernestoongaro, and a classic PAT carries write access to every repo that account can reach, not just the tap.

homebrew-tap also had no branch protection and no rulesets at all, so main was open to direct pushes.

What changed

actions/checkout now authenticates with ssh-key backed by a new HOMEBREW_TAP_DEPLOY_KEY secret, instead of token. A deploy key is scoped to a single repository and is tied to no human account.

Rollout order

This PR must land after the deploy key exists, or the next release cannot push the formula.

  1. Create the key and register it (done out-of-band — the private key must not pass through a PR):
    ssh-keygen -t ed25519 -N "" -C "cli-release@homebrew-tap" -f ./tap_key
    gh repo deploy-key add ./tap_key.pub --repo exploreomni/homebrew-tap --title "cli-release (write)" --allow-write
    gh secret set HOMEBREW_TAP_DEPLOY_KEY --repo exploreomni/cli < ./tap_key
    rm -f ./tap_key ./tap_key.pub
    
  2. Merge this PR.
  3. Cut a release and confirm the formula commit lands on the tap.
  4. Flip the protect-main ruleset on homebrew-tap (id 23698348) from evaluate to active.
  5. Revoke HOMEBREW_TAP_GITHUB_TOKEN on the personal account and delete the now-unused secret from this repo.

The ruleset is currently in evaluate mode, so it records violations without blocking. Nothing breaks until step 4.

The release job checked out exploreomni/homebrew-tap with
HOMEBREW_TAP_GITHUB_TOKEN, a classic PAT on a personal account created
2026-04-14 and never rotated. Despite the cosmetic
`git config user.name "github-actions[bot]"`, every push event on the tap
is authenticated as that human, and the PAT's scope spans every repo the
account can write to.

Swap it for an ed25519 deploy key scoped to the tap alone. This lets a
ruleset on homebrew-tap require PRs for all actors while allowing the
deploy key to bypass, so the release workflow remains the only thing that
can write to main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ernestoongaro

Copy link
Copy Markdown
Collaborator Author

Step 1 done

@ernestoongaro
ernestoongaro merged commit 752b9dc into main Sep 21, 2026
2 checks passed
@ernestoongaro
ernestoongaro deleted the harden/tap-deploy-key branch September 21, 2026 11:29
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.

2 participants