Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## v1.122.3

Closes the second self-update path, and corrects a packaging claim.

- **`UpdateSelf` now refuses an update it cannot verify.** v1.122.1 fixed the interactive updater, but the `UpdateSelf` CLI action is a separate implementation and kept the same fail-open shape: if no SHA-256 for `RackStack.exe` appeared in the release body it warned and replaced the running executable anyway. It now refuses and exits, matching the policy `Install-RackStack.ps1` already applied. In practice the hash has always been present, so this closes a latent gap rather than a live exposure -- but v1.122.1's notes described the fix more broadly than what actually shipped, and this makes that description true.
- **The test suite now asserts no module has a fail-open verification path**, rather than checking the one module that was edited. The narrower check passed while this second path survived; only verifying the shipped artifact caught it.
- **The Scoop manifest no longer claims the EXE is code-signed.** It is not Authenticode-signed -- that is precisely why antivirus engines flag it. The description now states what is actually true: Sigstore cosign signatures and SLSA Level 3 build provenance.

No module or CLI action changes (81 modules, 201 actions).

## v1.122.2

Packaging fix for the v1.122.1 release.
Expand Down
2 changes: 1 addition & 1 deletion Header.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
7h3 4b1d3r

.VERSION
1.122.2
1.122.3
.LAST UPDATED
07/28/2026

Expand Down
2 changes: 1 addition & 1 deletion Modules/00-Initialization.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ if (-not $PSCommandPath -and $script:ScriptPath) {
if (-not $script:ModuleRoot -and $script:ScriptPath) {
$script:ModuleRoot = [System.IO.Path]::GetDirectoryName($script:ScriptPath)
}
$script:ScriptVersion = "1.122.2"
$script:ScriptVersion = "1.122.3"
$script:ScriptStartTime = Get-Date

# Post-update cleanup: UpdateSelf / Rollback leave a `.pending-delete` sibling next to RackStack.exe.
Expand Down
10 changes: 9 additions & 1 deletion Modules/50-EntryPoint.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,15 @@ function Invoke-CLIAction {
}
Write-OutputColor " SHA256 verified." -color "Success"
} else {
Write-OutputColor " WARNING: No SHA256 in release body — skipping verification." -color "Warning"
# Fail closed, matching Install-RackStack.ps1's bootstrap policy: refusal is the
# default outcome of any verification failure, including a missing manifest entry.
# This replaces the running EXE, so an update whose integrity cannot be
# established must not be installed. (The interactive updater in 35-Utilities
# had the same fail-open shape and was fixed in v1.122.1.)
Remove-Item -LiteralPath $stageDir -Recurse -Force -ErrorAction SilentlyContinue
Write-OutputColor " No SHA256 for RackStack.exe in the release body — refusing to install an unverified update." -color "Error"
Write-OutputColor " Download and verify manually from: https://github.com/TheAbider/RackStack/releases/tag/$latestTag" -color "Info"
[Environment]::Exit(1)
}

# If a previous .old still exists (user ran UpdateSelf twice without launching in between),
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<a href="https://www.bestpractices.dev/projects/12921"><img alt="OpenSSF Best Practices" src="https://www.bestpractices.dev/projects/12921/badge"></a>
<a href="https://codecov.io/gh/TheAbider/RackStack"><img alt="codecov" src="https://codecov.io/gh/TheAbider/RackStack/branch/master/graph/badge.svg"></a>
<img alt="PSScriptAnalyzer 0 errors" src="https://img.shields.io/badge/PSScriptAnalyzer-0%20errors-brightgreen">
<img alt="5424 structural tests" src="https://img.shields.io/badge/structural%20tests-5424-brightgreen">
<img alt="5426 structural tests" src="https://img.shields.io/badge/structural%20tests-5426-brightgreen">
<img alt="Pester 312 tests" src="https://img.shields.io/badge/Pester-312%20tests-brightgreen">
<img alt="SLSA Level 3" src="https://slsa.dev/images/gh-badge-level3.svg">
</p>
Expand Down
2 changes: 1 addition & 1 deletion RackStack.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Environment-specific settings are configured via rackstack.config.json (a legacy defaults.json is still read).

.VERSION
1.122.2
1.122.3
.NOTES
- Requires Windows Server 2012 R2 or later (or Windows 10/11 for testing)
- Must be run as Administrator
Expand Down
2 changes: 1 addition & 1 deletion RackStack.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'RackStack.psm1'
ModuleVersion = '1.122.2'
ModuleVersion = '1.122.3'
GUID = 'c19b8e71-4a35-4f2b-9d06-8a24f7bc0e91'
Author = 'TheAbider'
CompanyName = 'TheAbider'
Expand Down
23 changes: 20 additions & 3 deletions Tests/Run-Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<#
.SYNOPSIS
Automated Test Runner for RackStack v1.122.2
Automated Test Runner for RackStack v1.122.3

.DESCRIPTION
Comprehensive non-interactive test suite covering:
Expand Down Expand Up @@ -10333,8 +10333,25 @@ try {
Write-TestResult "Update: Get-ReleaseAssetHash function exists" ($utilContent204 -match 'function\s+Get-ReleaseAssetHash\b')
Write-TestResult "Update: hash lookup is delegated, not inlined" ($utilContent204 -match '\$expectedHash\s*=\s*Get-ReleaseAssetHash\s')
Write-TestResult "Update: asset selection normalizes space/dot" ($utilContent204 -match '\$assetKey\s*=\s*\$assetName\s*-replace\s*''\[\\s\.\]'',\s*''\.''')
# The old fail-open text must never come back.
Write-TestResult "Update: no 'skipping verification' fail-open path" (-not ($utilContent204 -match 'skipping verification'))
# The old fail-open text must never come back — REPO-WIDE, not just in this module.
# Scoping this to 35-Utilities was a mistake: it passed while an identical fail-open
# survived in 50-EntryPoint's UpdateSelf action, and only an end-to-end check against the
# shipped monolithic caught it. Any code path that replaces a running binary or script must
# refuse an update it cannot verify, so assert across every module.
$failOpenHits204 = @(
Get-ChildItem -Path $modulesPath -Filter '*.ps1' -File |
Where-Object { (Get-Content $_.FullName -Raw) -match 'skipping verification' } |
ForEach-Object { $_.Name }
)
Write-TestResult "Update: no 'skipping verification' fail-open path in ANY module" `
($failOpenHits204.Count -eq 0) $(if ($failOpenHits204.Count) { "found in: $($failOpenHits204 -join ', ')" } else { "" })

# Both self-update implementations must refuse rather than warn-and-continue.
$entryContent204 = Get-Content "$modulesPath\50-EntryPoint.ps1" -Raw
Write-TestResult "Update: UpdateSelf refuses an unverified EXE" `
($entryContent204 -match 'refusing to install an unverified update')
Write-TestResult "Update: UpdateSelf exits rather than continuing" `
($entryContent204 -match 'refusing to install an unverified update[\s\S]{0,400}\[Environment\]::Exit\(1\)')
Write-TestResult "Update: missing hash refuses the install" ($utilContent204 -match 'refusing to install an unverified update')
# A refusal must actually return, not just print.
Write-TestResult "Update: refusal path returns before install" ($utilContent204 -match 'refusing to install an unverified update[\s\S]{0,400}\breturn\b')
Expand Down
2 changes: 1 addition & 1 deletion dist/scoop/rackstack.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
"version": "0.0.0",
"description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a code-signed EXE plus a PowerShell Gallery wrapper module exposing 201 structured CLI actions.",
"description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a standalone EXE with Sigstore cosign signatures and SLSA Level 3 build provenance, plus a PowerShell Gallery wrapper module exposing 201 structured CLI actions.",
"homepage": "https://github.com/TheAbider/RackStack",
"license": "MIT",
"url": "https://github.com/TheAbider/RackStack/releases/download/v0.0.0/RackStack.exe",
Expand Down