fix(git-ssh-sign): cross-check GitHub signing keys before picking one - #237
Open
mikesir87 wants to merge 1 commit into
Open
fix(git-ssh-sign): cross-check GitHub signing keys before picking one#237mikesir87 wants to merge 1 commit into
mikesir87 wants to merge 1 commit into
Conversation
The key command always signed with whichever key ssh-add -L listed
first. A host agent forwarding more than one key (e.g. a password
manager's own key alongside the one actually registered on GitHub) can
make that the wrong one - the commit signs fine but shows Unverified
on GitHub, since that key was never added to the committer's account.
When the repo's remote is on github.com and gh is authenticated, cross-
check the agent's keys against GET /users/{username}/ssh_signing_keys
(the public signing-keys list - deliberately not .keys, which is
auth-only and can diverge) and prefer whichever key actually matches,
falling back to the first key with a warning if none do. Cached for 5
minutes since this runs on every commit/tag and unauthenticated GitHub
API calls are capped at 60/hour per source IP.
On any other remote, or without gh, this is skipped entirely - no
network call, same first-key behavior as before. GitHub Enterprise
Server isn't covered yet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Michael Irwin <mikesir87@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ssh-signing-key-commandalways signed with whichever keyssh-add -Llisted first. A host agent forwarding more than one key (e.g. a password manager's own key alongside the one actually registered on GitHub) can make that the wrong one — the commit signs fine and verifies locally againstallowed_signers(which the script itself writes from the same pick), but shows Unverified on GitHub because that key was never added to the committer's account.github.comandghis authenticated, the command now cross-checks the agent's keys againstGET /users/{username}/ssh_signing_keys— the public, unauthenticated signing-keys endpoint — and prefers whichever agent key actually matches, falling back to the first key (with a stderr warning) if none do.github.com/{username}.keys: that only lists authentication keys and can diverge from the signing-key list.github-signing-keys.cachenext toallowed_signers, since this command runs on every commit/tag signature and unauthenticated GitHub API calls are capped at 60/hour per source IP.gh, this is skipped entirely — no network call, same first-key behavior as before.Spec choices worth flagging for review
permissions.network.allow: [api.github.com]— required for the cross-check to run underdeny-all. It's a permission grant, not a mandate; non-GitHub repos never trigger a request to it.github.comremotes trigger the lookup. Scoped narrowly on purpose rather than guessing at enterprise hostnames.gh api user, so it depends onghbeing installed and authenticated (gh auth status). Sandboxes withoutghsilently fall back to prior behavior.Test plan
go run ./scripts/verify-kit-spec git-ssh-sign— valid, no warnings.../scripts/test-kit.sh git-ssh-sign— TCK suite passes (validation, network policy, and a real container run of the install hook).github.comremote and one with agitlab.comremote — the GitLab repo produces byte-identical output to the old script (no cache file, no network call). Unit-tested the key-matchingawkagainst synthetic agent/GitHub key lists for both the match and no-match (fallback + warning) branches, and manually backdated the cache file to confirm it's refetched after the 5-minute TTL and reused within it (verified via a stubbedgh).../scripts/test-kit-e2e.sh(needsDOCKERHUB_USERNAME/DOCKERHUB_TOKEN, per CONTRIBUTING.md) andsbx run --kit .(nosbxbinary available in this environment).Origin
Found while debugging why a Docker Learn sandbox's commits showed Unverified on GitHub — the agent's forwarded SSH agent had two keys, and this kit picked the one that isn't registered on GitHub at all.
Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com