fix(install): a VERIFIED signature no longer kills the Windows install - #611
Conversation
cosign writes "Verified OK" to STDERR on the SUCCESS path. Windows
PowerShell 5.1 turns native-command stderr into a NativeCommandError
record, and this installer runs under `$ErrorActionPreference = 'Stop'`
(line 27), so that record is TERMINATING -- the install dies at the exact
moment verification passes. `2>$null` does not save it: 5.1 raises the
record before the redirection applies.
Measured on a real Windows 11 box against the published v0.10.17
installer:
Verifying cosign signature...
cosign.exe : Verified OK
+ & $cosign verify-blob `
+ FullyQualifiedErrorId : NativeCommandError
...and nothing was installed. So `tracebloc` cannot currently be
installed on Windows at all. It also takes tracebloc/client's installer
with it: Step 4 fails, which drops Step 5 to manual sign-in and Step 6 to
the hand-typed credential prompt -- observed on the same machine.
INVISIBLE ON POWERSHELL 7, which is why it survived: pwsh 7 does not make
error records out of native stderr, so this passes wherever it is tested
and fails on the Windows default. Verified both ways here.
THIS FILE ALREADY HELD THE FIX, 230 LINES UP. `Test-CosignRuns` opens
exactly this `$ErrorActionPreference = 'Continue'` window for
`cosign version` and explains why. The idiom was simply never applied to
the call that matters.
Not piped to Out-Null: `$LASTEXITCODE` is the entire verdict here and
piping a native command through a cmdlet is a documented way to lose it.
The window makes the record non-terminating; `2>$null` still discards the
text, so a real verification failure is unchanged -- it still exits 1.
Fixes the CLASS, not the instance: install-ps1-verify.sh now asserts that
every `& $...` invocation sits inside an ErrorActionPreference window
(2 calls, 2 windows), with a vacuity floor so it cannot pass by finding
none. Confirmed it reddens when the window is removed.
scripts/tests/install-ps1-verify.sh: 11 passed. shellcheck clean.
(The one behavioural-tier failure is pre-existing and environmental -- it
finds a real cosign on this machine's PATH; identical on an unmodified
tree.)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
saqlainsyed007
left a comment
There was a problem hiding this comment.
Reviewed at c198de79. This unbreaks the Windows install entirely — a critical, minimal fix with a class-level guard. Approving.
What it is (fix/install). cosign writes Verified OK to stderr when a signature verifies. Windows PowerShell 5.1 turns any native-command stderr into a NativeCommandError record, and this installer runs under $ErrorActionPreference = 'Stop' — so that record is terminating, and the install dies at the exact moment verification succeeds. 2>$null doesn't save it (5.1 raises the record before the redirection applies), so the published v0.10.17 installer fails outright: tracebloc client cannot currently be installed on Windows at all, and it takes tracebloc/client's installer down with it (Step 4 → manual sign-in → hand-typed credential prompt). It survived because it's invisible on PowerShell 7, which doesn't build error records from native stderr — so it passes wherever it's tested and fails on the Windows default.
The fix is the right one and already precedented in this file: wrap verify-blob in an $ErrorActionPreference = 'Continue' window (via try/finally restoring the previous value) — exactly the idiom Test-CosignRuns already uses 230 lines up for cosign version. It's deliberately not piped to Out-Null (that would lose $LASTEXITCODE, which is the entire verdict), the pre-set $global:LASTEXITCODE = 255 fail-closed default is preserved, and the if ($LASTEXITCODE -ne 0) reject path is unchanged — so a genuine verification failure still aborts with no TRACEBLOC_ALLOW_UNVERIFIED escape.
The test makes it a class, not an instance. install-ps1-verify.sh adds an invariant — every & $... native invocation must sit inside a Continue window (eap_windows >= native_calls), with a vacuity guard (0 native calls → fail, not a silent pass). I confirmed install.ps1 now has exactly 2 windows for its 2 native calls, so the next native call added without a window reddens CI. VERSION bumped 0.10.17→0.10.18 (the required version-bump-gate).
One heads-up, not a blocker: cli#609/#611/#612 all bump to 0.10.18, so whichever lands first will send the others red on version-check until they re-bump — expected gate behaviour, resolved at merge time on the source branch.
CI green, MERGEABLE, no open threads. LGTM.
…kend#2790) (#615) The 2026-08-31 staging settle refused cli: rc NOT tagged - v0.10.18 already exists and the delta DOES touch published files (bump VERSION on develop before the next release) v0.10.18 is tagged and the staging->develop delta touches `internal/*` and `scripts/install.ps1`, both declared publish paths. Re-tagging would make one tag name two different trees. PATCH, measured. Two commits, both `fix`: fix(ingest): report the physical destination table, not the requested name fix(install): a VERIFIED signature no longer kills the Windows install (#611) No feat, nothing breaking, so 0.10.18 -> 0.10.19. FIFTH INSTANCE OF THIS TODAY, and the count is the point. design-system-v2 hit it twice (v0.1.0, v0.1.1) and this is cli's turn; a fourth apparent case on design-system-v2 today turned out to be a STALE MIRROR rather than a missing bump, which is its own argument for automating the distinction instead of eyeballing it. Every release needs the bump the NEXT release is refused without, and doing it by hand means a refused settle is how we find out. `.github#372` builds `post-release-bump.yml` for exactly this. This repo needs its caller; that is the third checkbox on backend#2790. Part of tracebloc/backend#2790
The success path was fatal
cosign writes
Verified OKto stderr when a signature verifies. Windows PowerShell 5.1 turns any native-command stderr into aNativeCommandErrorrecord, and this installer runs under$ErrorActionPreference = 'Stop'(line 27) — so that record is terminating. The install dies at the exact moment verification succeeds.2>$nulldoes not prevent it: 5.1 raises the record before the redirection applies. The published v0.10.17 installer has that redirect and still fails.Measured on a real Windows 11 machine:
…and nothing was installed.
tracebloccannot currently be installed on Windows at all.It takes
tracebloc/client's installer with it, observed on the same machine: Step 4 fails → Step 5 can't register automatically and drops to manual sign-in → Step 6 falls back to the hand-typed credential prompt.Why it survived this long
It is invisible on PowerShell 7. pwsh 7 doesn't build error records out of native stderr, so this passes wherever it's tested and fails on the Windows default. I verified both directions: on pwsh 7 a native command writing to stderr under
Stopsails past; on the user's 5.1 it terminated.The fix was already in this file, 230 lines up
Test-CosignRunsopens exactly this$ErrorActionPreference = 'Continue'window forcosign version, and its comment explains why. The idiom was simply never applied toverify-blob.Two deliberate choices:
Out-Null.$LASTEXITCODEis the entire verdict here, and piping a native command through a cmdlet is a documented way to lose it. The window makes the record non-terminating;2>$nullstill discards the text.$LASTEXITCODEstill hitsexit 1. This only stops success from being fatal.Fixed the class, not the instance
install-ps1-verify.shnow asserts that every& $…invocation sits inside anErrorActionPreferencewindow — 2 calls, 2 windows — with a vacuity floor so it can't pass by finding none. It catches the next native call someone adds. Confirmed it reddens when the window is removed.Evidence
scripts/tests/install-ps1-verify.sh: 11 passed, including the new guard.shellcheck --severity=errorclean,bash -nclean,install.ps1parses clean.Resolve-Cosignfinding a real cosign on PATH) is pre-existing and environmental — identical on an unmodified tree, and it's my Mac's homebrew cosign.🤖 Generated with Claude Code
Note
Low Risk
Narrows installer error handling around an already-mandatory verify step; failed verification still fails closed; regression is covered by a new static guard in CI.
Overview
Fixes a Windows-only installer failure where a successful cosign signature check never completed the install. On Windows PowerShell 5.1,
cosign verify-blobprintsVerified OKto stderr; with$ErrorActionPreference = 'Stop', that becomes a terminatingNativeCommandErroreven though verification succeeded—2>$nulldoes not help on 5.1. The install aborted right after a valid signature (behavior that does not show up on PowerShell 7).The
cosign verify-blobinvocation is now wrapped in the same$ErrorActionPreference = 'Continue'try/finally pattern already used forcosign versioninTest-CosignRuns. Exit-code handling is unchanged:$LASTEXITCODEis still the verdict and real failures stillexit 1.install-ps1-verify.shadds guard 5d: count native& $…calls and require at least as manyContinuewindows so future native invocations cannot reintroduce the bug.Reviewed by Cursor Bugbot for commit c198de7. Bugbot is set up for automated code reviews on this repo. Configure here.