Skip to content

release-train: develop -> staging - #528

Open
LukasWodka wants to merge 1 commit into
stagingfrom
release-train/to-staging
Open

release-train: develop -> staging#528
LukasWodka wants to merge 1 commit into
stagingfrom
release-train/to-staging

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed release-train/to-staging branch (a mirror of develop), 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.ps1 now matches install.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 fetching cosign-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/.cert are missing. TRACEBLOC_ALLOW_UNVERIFIED=1 opts out only for “cannot verify”; a verification that ran and failed still refuses install. $AllowUnverified is 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) and install-ps1-functions.tests.ps1, which extracts Get-Sha256, Resolve-Cosign, and Test-CosignRuns from 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.

…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
@LukasWodka

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread scripts/install.ps1
(Join-Path $tmpDir $binaryFile) 2>$null
if ($LASTEXITCODE -ne 0) {
# No TRACEBLOC_ALLOW_UNVERIFIED branch here, deliberately.
# Verification RAN and said no.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)
Fix in Cursor Fix in Web

Triggered by project rule: Bugbot guide — tracebloc/cli

Reviewed by Cursor Bugbot for commit 3b88a85. Configure here.

@tracebloc-release-train tracebloc-release-train Bot added gate-nudge Toggled by the release train to (re-)fire the fr-gate and removed gate-nudge Toggled by the release train to (re-)fire the fr-gate labels Aug 18, 2026
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