# Integration regression: actual Windows labels, child process tokens, and an # NSIS bootstrap that writes to TEMP and exits without installing anything. [CmdletBinding()] param( [string]$NsisCompiler = (Join-Path $env:LOCALAPPDATA 'tauri/NSIS/makensis.exe') ) $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest $prepare = Join-Path $PSScriptRoot 'prepare-windows-bundle.ps1' & $prepare -CheckProcessOnly if (-not (Test-Path -LiteralPath $NsisCompiler)) { throw "NSIS compiler not found: $NsisCompiler" } function Assert([bool]$Condition, [string]$Message) { if (-not $Condition) { throw $Message } } $testId = [Guid]::NewGuid().ToString('N') $tempRoot = [IO.Path]::GetFullPath([IO.Path]::GetTempPath()) $fixture = Join-Path $tempRoot "rmic bundle test $testId" $probeFile = Join-Path $tempRoot "rmic-nsis-temp-$testId.txt" $installer = Join-Path $fixture 'bundle/nsis/probe-setup.exe' $main = Join-Path $fixture 'cam-desktop.exe' try { New-Item -ItemType Directory -Force -Path (Join-Path $fixture 'bundle/nsis'), (Join-Path $fixture 'nsis/x64') | Out-Null Copy-Item -LiteralPath (Join-Path $env:WINDIR 'System32/whoami.exe') -Destination $main $accessBefore = (Get-Acl -LiteralPath $main).Sddl # A small real NSIS executable exercises its early TEMP validation and # plugin extraction without touching app files, registry, or shortcuts. $source = Join-Path $fixture 'probe.nsi' @" Unicode true Name "RMIC temporary directory probe" OutFile "$($installer.Replace('$', '$$'))" RequestExecutionLevel user SilentInstall silent Section InitPluginsDir FileOpen `$0 "`$TEMP\rmic-nsis-temp-$testId.txt" w IfErrors failed FileWrite `$0 "NSIS TEMP writable" FileClose `$0 SetErrorLevel 0 Quit failed: SetErrorLevel 3 SectionEnd "@ | Set-Content -LiteralPath $source -Encoding UTF8 & $NsisCompiler /V2 $source Assert ($LASTEXITCODE -eq 0) 'Cannot compile the NSIS TEMP probe.' & icacls.exe $fixture /setintegritylevel '(OI)(CI)L' | Out-Null Assert ($LASTEXITCODE -eq 0) 'Cannot create a Low integrity fixture.' & icacls.exe $main /setintegritylevel L | Out-Null Assert ($LASTEXITCODE -eq 0) 'Cannot create an explicit Low executable label.' $before = (& $main /groups) -join "`n" Assert ($LASTEXITCODE -eq 0 -and $before -match 'S-1-16-4096') 'Low executable did not start with a Low token.' $rejected = $false try { & $prepare -OutputDir $fixture -CheckOnly } catch { if ($_.Exception.Message -notmatch 'Low / Untrusted') { throw } $rejected = $true } Assert $rejected 'Read-only artifact verification accepted a Low label.' Assert ([RmicBundleIntegrity]::ReadLabel($installer) -match ';LW\)') 'Read-only verification changed the installer.' # A Low process must fail before it tries to modify any output labels. $lowShell = Join-Path $fixture 'low-shell.exe' Copy-Item -LiteralPath (Join-Path $env:WINDIR 'System32/WindowsPowerShell/v1.0/powershell.exe') -Destination $lowShell # Windows PowerShell 5 treats redirected native stderr as ErrorRecord objects. # This command is expected to fail, so collect its diagnostic before asserting. try { $ErrorActionPreference = 'Continue' $lowOutput = (& $lowShell -NoProfile -ExecutionPolicy Bypass -File $prepare -CheckProcessOnly 2>&1) -join "`n" } finally { $ErrorActionPreference = 'Stop' } Assert ($LASTEXITCODE -ne 0 -and $lowOutput -match 'requires Medium integrity') 'Low packaging process was not rejected.' & $prepare -OutputDir $fixture & $prepare -OutputDir $fixture -CheckOnly & $prepare -OutputDir $fixture $after = (& $main /groups) -join "`n" Assert ($LASTEXITCODE -eq 0 -and $after -match 'S-1-16-(\d+)' -and [int]$Matches[1] -ge 8192) 'Repaired executable still starts below Medium integrity.' Assert ((Get-Acl -LiteralPath $main).Sddl -eq $accessBefore) 'Repair changed the executable DACL.' # The repaired shell now starts at Medium even from an elevated test runner. # Verify that repairing owned Low outputs does not require elevation. $mediumFixture = Join-Path $fixture 'medium repair' New-Item -ItemType Directory -Path $mediumFixture | Out-Null & icacls.exe $mediumFixture /setintegritylevel '(OI)(CI)L' | Out-Null Assert ($LASTEXITCODE -eq 0) 'Cannot prepare the Medium-process repair fixture.' $mediumOutput = (& $lowShell -NoProfile -ExecutionPolicy Bypass -File $prepare -OutputDir $mediumFixture 2>&1) -join "`n" Assert ($LASTEXITCODE -eq 0) "Repair failed at Medium integrity: $mediumOutput" Assert ([RmicBundleIntegrity]::ReadLabel($mediumFixture) -match ';ME\)') 'Medium process did not repair the output label.' $probe = Start-Process -FilePath $installer -ArgumentList '/S' -PassThru -WindowStyle Hidden try { Assert ($probe.WaitForExit(15000)) 'NSIS TEMP probe timed out.' Assert ($probe.ExitCode -eq 0) "NSIS TEMP probe failed: $($probe.ExitCode)" Assert ((Get-Content -LiteralPath $probeFile -Raw) -eq 'NSIS TEMP writable') 'NSIS could not write to the normal TEMP directory.' } finally { if (-not $probe.HasExited) { $probe.Kill(); $probe.WaitForExit() } $probe.Dispose() } $emptyOutput = Join-Path $fixture 'empty' & $prepare -OutputDir $emptyOutput $rejected = $false try { & $prepare -OutputDir $emptyOutput -CheckOnly } catch { if ($_.Exception.Message -notmatch 'No NSIS installer') { throw } $rejected = $true } Assert $rejected 'Artifact verification accepted missing installers.' # Exercise automatic Cargo output discovery, debug target selection and the # separate host build-script directory, without invoking a real Rust build. $savedEnvironment = @{} foreach ($name in @('CARGO_TARGET_DIR', 'TAURI_ENV_TARGET_TRIPLE', 'TAURI_ENV_DEBUG')) { $savedEnvironment[$name] = @{ Exists = Test-Path -LiteralPath "Env:$name" Value = [Environment]::GetEnvironmentVariable($name, 'Process') } } try { $env:CARGO_TARGET_DIR = Join-Path $fixture 'cargo cache' $env:TAURI_ENV_TARGET_TRIPLE = 'x86_64-pc-windows-msvc' $env:TAURI_ENV_DEBUG = 'true' $hostBuildDir = Join-Path $env:CARGO_TARGET_DIR 'debug/build/probe' New-Item -ItemType Directory -Force -Path $hostBuildDir | Out-Null $hostScript = Join-Path $hostBuildDir 'build-script-build.exe' Copy-Item -LiteralPath $main -Destination $hostScript & icacls.exe $env:CARGO_TARGET_DIR /setintegritylevel '(OI)(CI)L' | Out-Null Assert ($LASTEXITCODE -eq 0) 'Cannot create Low host build outputs.' & $prepare Assert ([RmicBundleIntegrity]::ReadLabel($hostScript) -match ';ME\)') 'Host build script was not repaired.' $targetOutput = Join-Path $env:CARGO_TARGET_DIR 'x86_64-pc-windows-msvc/debug/bundle/nsis' Assert (Test-Path -LiteralPath $targetOutput) 'Cargo target directory or debug profile was ignored.' } finally { foreach ($name in $savedEnvironment.Keys) { if ($savedEnvironment[$name].Exists) { Set-Item -LiteralPath "Env:$name" -Value $savedEnvironment[$name].Value } else { Remove-Item -LiteralPath "Env:$name" -ErrorAction SilentlyContinue } } } Write-Host 'PASS: Low token reproduction, process guard, read-only rejection, label repair, unchanged DACL, repeat repair, NSIS TEMP bootstrap, missing artifacts, custom Cargo output and host build scripts.' } finally { # Only delete this test's uniquely named fixture, after checking its absolute path. $resolvedFixture = [IO.Path]::GetFullPath($fixture) if ($resolvedFixture.StartsWith($tempRoot.TrimEnd('\') + '\', [StringComparison]::OrdinalIgnoreCase) -and (Split-Path -Leaf $resolvedFixture) -eq "rmic bundle test $testId") { if (Test-Path -LiteralPath $resolvedFixture) { Remove-Item -LiteralPath $resolvedFixture -Recurse -Force } } if (Test-Path -LiteralPath $probeFile) { Remove-Item -LiteralPath $probeFile -Force } }