release-train: develop -> staging - #528
Conversation
…cosign (#523) install.ps1 gated cosign verification on `if (Get-Command cosign)`. On a fresh Windows box cosign is never present, so the default path printed (cosign not installed; SHA256 verified, signature skipped) and installed. The SHA256 it kept is same-channel — SHA256SUMS ships from the same release as the binary, so whoever could swap one could swap the other. It proves the download finished, not who built it. That made README.md:75 ("Signature verification is mandatory ... fails closed", no platform qualifier) false on Windows, and only on Windows: install.sh has bootstrapped a pinned cosign and failed closed since backend#889. The README needs no edit — this makes the existing claim true. Windows now does what Linux and macOS do: bootstrap a pinned, checksum-verified cosign, and refuse to install when it can't. TRACEBLOC_ALLOW_UNVERIFIED=1 is the one escape, and it covers "cannot verify" only — never a verification that ran and FAILED, which is tampering evidence no env var should override. Two things this does that install.sh does not have to: - The bootstrap fetches cosign-windows-amd64.exe on BOTH architectures. Sigstore has never published a Windows arm64 build, so a per-arch name 404s and locks Windows-on-ARM out permanently (the same bug as tracebloc/client#734). Verification is over bytes, so the verifier's instruction set cannot change the verdict. - Test-CosignRuns separates "cosign won't start here" from "the signature is bad". They arrive through the same channel and warrant opposite messages — only one means the artifact may be tampered with. Absent x64 emulation on Windows-on-ARM is the case that makes this real, and "install cosign" would be useless advice there. Also sets a TLS 1.2 floor: PS 5.1 defaults to SSL3/TLS1.0 on older Windows, and every fetch here carries either the binary or the verifier that authenticates it. Tests — scripts/tests/install-ps1-verify.sh, install-verify.sh's sibling, wired into the same CI job. Against develop's installer: 0 passed, 5 failed. After: 5 passed, 0 failed. install.ps1 cannot be driven end-to-end on the Linux runner (it ends in Windows-registry PATH writes), so the behavioural tier extracts the helpers from the real file BY AST and executes them — a copy would pass while production broke. Six guards, each mutation-proven, each mutation asserted to have applied: [bool]$env:... instead of -eq '1' -> 4 fail checksum mismatch stops refusing -> 1 fail $LASTEXITCODE not armed before the probe -> 1 fail an opt-out on a FAILED verification -> 1 fail the no-cosign degrade restored -> 1 fail a \$ escape in a message -> 1 fail Three of those are bugs this change made and this tier caught before review: - $AllowUnverified was [bool]$env:TRACEBLOC_ALLOW_UNVERIFIED. Every non-empty string casts to $true in PowerShell, so setting it to 0 would have switched the bypass ON. - The bootstrap restated Get-Arch's logic minus its PROCESSOR_ARCHITEW6432 handling, so a 32-bit PowerShell host would have refused. Removed: the asset is arch-independent, there was nothing to branch on. - "Pin a signed \$env:RELEASE_VERSION" rendered as "Pin a signed ," — PowerShell escapes with a backtick, so \$ prints a backslash and expands the variable. Now a check of its own. One test in this tier was vacuous on its first writing: a "stale exit code" assertion built on an absent path, which throws and returns before ever reading $LASTEXITCODE. The mutation caught it — M3 applied and nothing reddened. Replaced with the input that is actually reachable: a PowerShell shim (scoop and chocolatey install cosign.ps1), which `&` dispatches in-process and which sets no $LASTEXITCODE at all. backend#2078
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3b88a85. Configure here.
| (Join-Path $tmpDir $binaryFile) 2>$null | ||
| if ($LASTEXITCODE -ne 0) { | ||
| # No TRACEBLOC_ALLOW_UNVERIFIED branch here, deliberately. | ||
| # Verification RAN and said no. |
There was a problem hiding this comment.
Verify skips stale exit preset
High Severity
Test-CosignRuns presets $global:LASTEXITCODE to 255 so a PowerShell shim that never sets an exit code cannot inherit a stale 0. The mandatory verify-blob call that actually gates the install does not. After a shim that exits 0 on version, a no-op verify-blob leaves $LASTEXITCODE at 0, so the installer prints that the cosign signature is valid and installs without verifying.
Additional Locations (1)
Triggered by project rule: Bugbot guide — tracebloc/cli
Reviewed by Cursor Bugbot for commit 3b88a85. Configure here.


Automated promotion by the release train (RFC-0008 D14). Head is the train-managed
release-train/to-stagingbranch (a mirror ofdevelop), so it never collides with a human PR. Merged only when the fr-gate is green.Note
Medium Risk
Changes the privileged Windows install path and verification policy; behavior is hardened with fail-closed defaults and new CI harnesses, but misconfiguration or bootstrap bugs could block installs on Windows.
Overview
Windows
install.ps1now matchesinstall.sh: cosign signature verification is mandatory (RFC-0001 R8, backend#2078). The old path that installed on SHA256 alone when cosign was missing is removed.The script bootstraps a pinned cosign (
v2.4.1) with checksum verification against sigstore’s published sums, always fetchingcosign-windows-amd64.exe(no arm64 asset). It fails closed when cosign cannot be obtained, won’t run (e.g. ARM without x64 emulation), or.sig/.certare missing.TRACEBLOC_ALLOW_UNVERIFIED=1opts out only for “cannot verify”; a verification that ran and failed still refuses install.$AllowUnverifiedis parsed as literal'1'only (not[bool]on env). TLS 1.2 is enforced for downloads.CI adds
install-ps1-verify.sh(grep guards + pwsh behavioral tier) andinstall-ps1-functions.tests.ps1, which extractsGet-Sha256,Resolve-Cosign, andTest-CosignRunsfrom the real installer via AST rather than duplicating logic.Reviewed by Cursor Bugbot for commit 3b88a85. Bugbot is set up for automated code reviews on this repo. Configure here.