fix(windows): hardening modules never ran (SetupComplete quoting bug)
All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (push) Successful in 4m12s

VM runtime test (offline disk mount) revealed SetupComplete.cmd ran but its inline
multi-line `powershell -Command` (cmd ^-continuation + nested escaped quotes) failed
to parse ("string is missing the terminator") -> the §A-H modules never executed.
Offline CI assertions only proved the files were BAKED, not that they RUN.

Fix: move the module runner into hardening/Invoke-Hardening.ps1 and call it with
-File (no cmd quoting). Runner runs 00*..08* in order then Verify (writes
verify-report.json in-line as SYSTEM; reboot/PIN-dependent gates show pending).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
sysadmin
2026-06-09 00:34:05 +01:00
parent d690b14fc4
commit ba3ef0d45a
2 changed files with 22 additions and 17 deletions

View File

@@ -0,0 +1,17 @@
#Requires -Version 5.1
<# SilverMetal Enhanced - Windows | First-boot hardening runner.
Runs the §A-H modules (00*.ps1 .. 08*.ps1) in order, then the Verify gate.
Called by SetupComplete.cmd via -File (no cmd-quoting fragility). Logs to the
pipeline that SetupComplete redirects.
#>
[CmdletBinding()] param()
$ErrorActionPreference = 'Continue'
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
Write-Host "=== SilverMetal hardening modules ==="
Get-ChildItem (Join-Path $here '0*.ps1') | Sort-Object Name | ForEach-Object {
Write-Host "--> $($_.Name)"
try { & $_.FullName } catch { Write-Warning "$($_.Name) FAILED: $_" }
}
Write-Host "=== Verify (effects needing reboot/PIN will show pending) ==="
try { & (Join-Path $here 'Verify-SilverMetalWindows.ps1') } catch { Write-Warning "Verify error: $_" }
Write-Host "=== SilverMetal hardening runner done ==="

View File

@@ -1,15 +1,12 @@
@echo off
REM ===========================================================================
REM SilverMetal Enhanced - Windows : first-boot entry point.
REM Invoked once by autounattend.xml FirstLogonCommands. Runs the shared
REM hardening/ modules in order, logs to disk, then schedules verification.
REM
REM The hardening/ modules are staged into C:\Windows\Setup\Scripts\hardening
REM by build.ps1 (stage 4). They are SHARED with the self-apply track.
REM Windows runs %WINDIR%\Setup\Scripts\SetupComplete.cmd automatically (as
REM SYSTEM) at the end of setup. It hands off to Invoke-Hardening.ps1 via -File
REM to avoid cmd/PowerShell quoting fragility (an inline -Command one-liner
REM here previously failed to parse, so the §A-H modules never ran).
REM
REM Design: ../../iso-builder.md Controls: ../../hardening-spec.md
REM SCAFFOLD (M0): module bodies stubbed; safe to run (modules log and no-op
REM until implemented at M1).
REM ===========================================================================
set LOG=C:\Windows\Setup\Scripts\silvermetal-firstboot.log
@@ -17,16 +14,7 @@ set HARD=C:\Windows\Setup\Scripts\hardening
echo [%DATE% %TIME%] SilverMetal first-boot start >> "%LOG%"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$ErrorActionPreference='Stop';" ^
"Get-ChildItem '%HARD%\0*.ps1' | Sort-Object Name | ForEach-Object {" ^
" Write-Host \"--> $($_.Name)\";" ^
" & $_.FullName *>> '%LOG%'" ^
"}" >> "%LOG%" 2>&1
REM Register the verification task to run after the first full boot/login.
schtasks /Create /TN "SilverMetal\Verify" /SC ONLOGON /RL HIGHEST /F ^
/TR "powershell -NoProfile -ExecutionPolicy Bypass -File %HARD%\Verify-SilverMetalWindows.ps1" >> "%LOG%" 2>&1
powershell -NoProfile -ExecutionPolicy Bypass -File "%HARD%\Invoke-Hardening.ps1" >> "%LOG%" 2>&1
echo [%DATE% %TIME%] SilverMetal first-boot done >> "%LOG%"
exit /b 0