Skip to content

Prevent silent attestation downgrade on gem push - #9825

Open
hsbt wants to merge 3 commits into
masterfrom
push-attestation-downgrade
Open

Prevent silent attestation downgrade on gem push#9825
hsbt wants to merge 3 commits into
masterfrom
push-attestation-downgrade

Conversation

@hsbt

@hsbt hsbt commented Aug 28, 2026

Copy link
Copy Markdown
Member

gem push wrapped the whole attested push in rescue StandardError. A failure to read a file given to --attestation printed a warning and published the gem unattested with exit 0, contradicting the comment right above that branch. The same rescue covered the HTTP POST, so a read timeout after the server had already accepted the multipart push retried it unattested, which also lets an on-path attacker strip attestations by cutting the first connection.

Only the opportunistic auto-signing step falls back now. Errors from an explicit --attestation abort the push, and the request stays outside the rescue.

Three smaller problems from the same review are fixed here too. attest! returned only the tempfile path, so GC could unlink the bundle before it was read. ENV["GITHUB_ACTIONS"] was tested for truthiness instead of against "true". Attestation bundles were concatenated into a JSON array unvalidated. The test helper also scrubs GITHUB_ACTIONS, which was making CI spawn real gem exec sigstore-cli subprocesses.

#9325

hsbt and others added 3 commits August 31, 2026 14:47
On GitHub Actions the push tests inherited the real variable, took the
auto-attestation path, and spawned `gem exec sigstore-cli` subprocesses.
Scrubbing it in setup also made the host and engine skip guards decide
nothing, so those tests now set it themselves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GitHub Actions documents the variable as "true", so any other value,
including "false", should not trigger the auto-attestation path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The whole attested push was wrapped in rescue StandardError. A failure to
read a file given to --attestation printed a warning and published the gem
unattested with exit 0, and a network error after the server may have
accepted the multipart push retried it unattested, letting an on-path
attacker strip attestations by cutting the first connection. Only the
opportunistic auto-signing step falls back now.

attest! also returned just the tempfile path, so GC could unlink the
bundle before it was read, which fell into that same rescue. Each bundle
is now validated as a JSON object before it is sent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hsbt
hsbt force-pushed the push-attestation-downgrade branch from 5aad204 to 9ce35a5 Compare August 31, 2026 05:48
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