Skip to content

fix(install): a VERIFIED signature no longer kills the Windows install - #611

Merged
shujaatTracebloc merged 1 commit into
developfrom
fix/cli-windows-install-stderr-terminates
Aug 31, 2026
Merged

fix(install): a VERIFIED signature no longer kills the Windows install#611
shujaatTracebloc merged 1 commit into
developfrom
fix/cli-windows-install-stderr-terminates

Conversation

@shujaatTracebloc

@shujaatTracebloc shujaatTracebloc commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The success path was fatal

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' (line 27) — so that record is terminating. The install dies at the exact moment verification succeeds.

2>$null does 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:

Verifying cosign signature...
cosign.exe : Verified OK
+             & $cosign verify-blob `
+ FullyQualifiedErrorId : NativeCommandError

…and nothing was installed. tracebloc cannot 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 Stop sails past; on the user's 5.1 it terminated.

The fix was already in this file, 230 lines up

Test-CosignRuns opens exactly this $ErrorActionPreference = 'Continue' window for cosign version, and its comment explains why. The idiom was simply never applied to verify-blob.

Two deliberate choices:

  • 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.
  • A real verification failure is unchanged — non-zero $LASTEXITCODE still hits exit 1. This only stops success from being fatal.

Fixed 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 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=error clean, bash -n clean, install.ps1 parses clean.
  • The one behavioural-tier failure (Resolve-Cosign finding 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-blob prints Verified OK to stderr; with $ErrorActionPreference = 'Stop', that becomes a terminating NativeCommandError even though verification succeeded—2>$null does 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-blob invocation is now wrapped in the same $ErrorActionPreference = 'Continue' try/finally pattern already used for cosign version in Test-CosignRuns. Exit-code handling is unchanged: $LASTEXITCODE is still the verdict and real failures still exit 1.

install-ps1-verify.sh adds guard 5d: count native & $… calls and require at least as many Continue windows 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.

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>
@shujaatTracebloc shujaatTracebloc self-assigned this Aug 31, 2026
@shujaatTracebloc
shujaatTracebloc requested review from LukasWodka and saqlainsyed007 and removed request for saqlainsyed007 August 31, 2026 12:03
@shujaatTracebloc
shujaatTracebloc marked this pull request as ready for review August 31, 2026 12:06
@shujaatTracebloc
shujaatTracebloc requested review from aptracebloc and removed request for LukasWodka August 31, 2026 12:45
@saqlainsyed007
saqlainsyed007 requested review from saadqbal and removed request for aptracebloc August 31, 2026 12:46
@shujaatTracebloc
shujaatTracebloc requested review from aptracebloc and saqlainsyed007 and removed request for aptracebloc and saadqbal August 31, 2026 12:47

@saqlainsyed007 saqlainsyed007 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@shujaatTracebloc
shujaatTracebloc merged commit 9a361d5 into develop Aug 31, 2026
46 of 48 checks passed
@shujaatTracebloc
shujaatTracebloc deleted the fix/cli-windows-install-stderr-terminates branch August 31, 2026 13:36
LukasWodka added a commit that referenced this pull request Aug 31, 2026
…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
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.

3 participants