Skip to content

Pin key fingerprints so a corrupted key cannot deploy - #1

Merged
Aswinmcw merged 1 commit into
mainfrom
pin-fingerprints
Aug 28, 2026
Merged

Pin key fingerprints so a corrupted key cannot deploy#1
Aswinmcw merged 1 commit into
mainfrom
pin-fingerprints

Conversation

@Aswinmcw

Copy link
Copy Markdown
Member

ssh-keygen -l validates structure, not authenticity. Flipping one bit in a key's material leaves a line that still parses, still reports 256 ... (ED25519), and still passes every check we had — only the fingerprint moves:

original  exit=0  SHA256:gWAoI59eLhaNK6FGvQDobXNmxPZUCkf+HUNh329gZAg
tampered  exit=0  SHA256:36ChMPyUQ1wPbUeDS+/bBk29JUyV50TmuYlYcX9QenU

A key corrupted that way would deploy, land in a new machine's authorized_keys, and silently not work — you'd believe you had four ways into that box and have three.

fingerprints.txt now pins the SHA256 of every key; validate.sh refuses to build while it and keys.txt disagree. Regenerate with sh scripts/fingerprints.sh and commit both together.

The pin also buys reviewability, which may matter more day to day: a reviewer skims past a 68-character base64 blob, but a changed SHA256: line is legible.

Verified — all blocked: the bit-flip, a key added without regenerating, a key removed, a missing fingerprints.txt. And regenerating unblocks.

ssh-keygen -l validates structure, not authenticity. Flipping one bit in a key's
material leaves a line that still parses, still reports 256-bit ED25519, and
still passes every check we had -- only the fingerprint moves. Demonstrated:
both the original and the tampered line exit 0 under ssh-keygen -lf.

A key corrupted that way would have deployed, reached a new machine's
authorized_keys and silently not worked, because no private key matches it. You
would believe you had four ways into that box and have three.

fingerprints.txt now pins the SHA256 of every key and validate.sh refuses to
build while it and keys.txt disagree. Regenerate with scripts/fingerprints.sh
and commit both together.

The pin also buys reviewability, which may matter more: a reviewer skims past a
68-character base64 blob, but a changed SHA256 line is legible. Key material
cannot change without the change appearing in a readable form in the same diff.

Verified against the bit-flip, an added key, a removed key and a missing
fingerprints.txt -- all blocked -- and that regenerating unblocks. An earlier
attempt at the last case failed because the key I appended reused an existing
blob and tripped the duplicate guard instead; the test was wrong, not the code.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
keys 8a75baf Aug 28 2026, 07:22 AM

@Aswinmcw
Aswinmcw merged commit 909a813 into main Aug 28, 2026
5 checks passed
@Aswinmcw
Aswinmcw deleted the pin-fingerprints branch August 28, 2026 07:22
Aswinmcw added a commit that referenced this pull request Aug 28, 2026
'push:' with no branch filter fired alongside 'pull_request:', so every pull
request commit ran the whole suite twice -- two identical Checks and two
identical E2E runs, visible on PR #1. Restricting the push trigger to main
leaves one run per PR commit plus one on main after a merge, which is what
verifies the squashed result rather than the branch head.

Tradeoff: a branch pushed with no PR open now gets no CI. That is the right way
round, because main is protected by required status checks and nothing reaches
it without a PR.
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