From 166e4d8d0c91b061e411aed94d736b59cb6e6f12 Mon Sep 17 00:00:00 2001 From: sysadmin Date: Tue, 9 Jun 2026 09:51:24 +0100 Subject: [PATCH] fix(welcome): silent admin elevation via offline UAC auto-approve policy + Start-Process RunAs launch (scheduled-task approach failed un-elevated) Co-Authored-By: Claude Sonnet 4.6 --- .../installer/autounattend/autounattend.xml | 18 +++++++---------- windows/installer/build.ps1 | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/windows/installer/autounattend/autounattend.xml b/windows/installer/autounattend/autounattend.xml index 29d6461..a68c48d 100644 --- a/windows/installer/autounattend/autounattend.xml +++ b/windows/installer/autounattend/autounattend.xml @@ -113,21 +113,17 @@ bootstrap-OneTime!true</PlainText></Password> </AutoLogon> <!-- - FirstLogonCommands: launch the Welcome wizard ELEVATED (full admin token) without - a UAC prompt by registering it as a scheduled task with /RL HIGHEST /IT, then - triggering it immediately. The sm-bootstrap account is torn down by ApplyService - on wizard completion. + FirstLogonCommands: launch the Welcome wizard ELEVATED (full admin token). + The offline UAC auto-approve policy baked into the image (ConsentPromptBehaviorAdmin=0, + PromptOnSecureDesktop=0) means Start-Process -Verb RunAs silently elevates without + a UAC prompt during this ephemeral sm-bootstrap session. The sm-bootstrap account + is torn down by ApplyService on wizard completion. --> <FirstLogonCommands> <SynchronousCommand wcm:action="add" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"> <Order>1</Order> - <CommandLine>cmd /c schtasks /Create /TN "SilverOSWelcome" /TR &quot;&quot;C:\Program Files\SilverOS\Welcome\SilverOS.Welcome.App.exe&quot;&quot; /SC ONCE /ST 23:59 /RL HIGHEST /IT /F</CommandLine> - <Description>Register SilverOS Welcome as an elevated interactive scheduled task</Description> - </SynchronousCommand> - <SynchronousCommand wcm:action="add" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"> - <Order>2</Order> - <CommandLine>cmd /c schtasks /Run /TN "SilverOSWelcome"</CommandLine> - <Description>Run the SilverOS Welcome wizard elevated in the active session</Description> + <CommandLine>cmd /c powershell -NoProfile -ExecutionPolicy Bypass -Command &quot;Start-Process -FilePath 'C:\Program Files\SilverOS\Welcome\SilverOS.Welcome.App.exe' -Verb RunAs&quot;</CommandLine> + <Description>Launch SilverOS Welcome elevated</Description> </SynchronousCommand> </FirstLogonCommands> <RegisteredOwner>SilverMetal</RegisteredOwner> diff --git a/windows/installer/build.ps1 b/windows/installer/build.ps1 index 925c3b2..36ee376 100644 --- a/windows/installer/build.ps1 +++ b/windows/installer/build.ps1 @@ -212,6 +212,26 @@ function Invoke-ServiceWim { # Stage Welcome app + flavours while the WIM is still mounted. Copy-WelcomePayload + + # Bake offline UAC auto-approve policy so the Welcome wizard (launched via + # Start-Process -Verb RunAs in FirstLogonCommands) silently elevates during + # the ephemeral sm-bootstrap session without a UAC prompt. + # UAC stays enabled (EnableLUA=1); the wizard's hardening re-tightens the + # policy for the daily user. Only applies when Welcome is enabled. + if ($env:SILVERMETAL_WELCOME_ENABLED -ne '0') { + Write-Stage 'Stage 3d: bake offline UAC auto-approve policy (silent elevation for sm-bootstrap)' + $hive = Join-Path $mount 'Windows\System32\config\SOFTWARE' + & reg load HKLM\SM_OFFLINE "$hive" | Out-Null + if ($LASTEXITCODE -ne 0) { throw 'reg load SOFTWARE hive failed' } + try { + & reg add 'HKLM\SM_OFFLINE\Microsoft\Windows\CurrentVersion\Policies\System' /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f | Out-Null + & reg add 'HKLM\SM_OFFLINE\Microsoft\Windows\CurrentVersion\Policies\System' /v PromptOnSecureDesktop /t REG_DWORD /d 0 /f | Out-Null + Write-Host ' ConsentPromptBehaviorAdmin=0, PromptOnSecureDesktop=0 written to offline SOFTWARE hive.' + } finally { + [gc]::Collect(); Start-Sleep -Milliseconds 500 + & reg unload HKLM\SM_OFFLINE | Out-Null + } + } } finally { Dismount-WindowsImage -Path $mount -Save | Out-Null }