# scripts/run_tests_sandboxed.ps1 <# .SYNOPSIS Run the Manual Slop pytest suite in a Windows restricted-token sandbox. .DESCRIPTION Acquires a Windows restricted token (drops dangerous privileges), sets the current directory to the project root, and invokes pytest with --basetemp under tests/artifacts/ + --config pointing inside tests/artifacts/_isolation_workspace_/config_overrides.toml. The FR1 Python audit guard in tests/conftest.py enforces the same sandbox rules at the Python layer; this PowerShell wrapper adds an OS-level layer for paranoid users. .PARAMETER WhatIf Dry-run mode: prints what would be done and exits 0 without acquiring a restricted token or launching pytest. .PARAMETER TestPath Pytest test path (default: tests/). .PARAMETER ConfigPath Optional path to config.toml. Empty string = conftest.py auto-defaults to tests/artifacts/_isolation_workspace_/config_overrides.toml. .EXAMPLE pwsh -File scripts/run_tests_sandboxed.ps1 -WhatIf .EXAMPLE pwsh -File scripts/run_tests_sandboxed.ps1 -TestPath tests/test_paths.py .NOTES Requires Windows + PowerShell 7+. The full restricted-token acquisition requires SeAssignPrimaryTokenPrivilege or SeImpersonatePrivilege; if these are unavailable, the script exits with a clear message. Use -WhatIf for a no-op dry-run. .LINK scripts/tier2/run_tier2_sandboxed.ps1 (template) scripts/audit_test_sandbox_violations.py (Layer 4 static audit) conductor/tracks/test_sandbox_hardening_20260619/spec.md (FR5) #> [CmdletBinding()] param( [switch]$WhatIf, [string]$TestPath = "tests/", [string]$ConfigPath = "", [string]$ProjectRoot = "" ) $ErrorActionPreference = "Stop" if (-not $ProjectRoot) { $ProjectRoot = (Resolve-Path "$PSScriptRoot/..").Path } else { $ProjectRoot = (Resolve-Path $ProjectRoot).Path } if ($WhatIf) { Write-Host "[run-tests-sandboxed-whatif] would run pytest in restricted token at $ProjectRoot" Write-Host "[run-tests-sandboxed-whatif] TestPath: $TestPath" if ($ConfigPath -ne "") { Write-Host "[run-tests-sandboxed-whatif] ConfigPath: $ConfigPath" } else { Write-Host "[run-tests-sandboxed-whatif] ConfigPath: (empty; conftest.py auto-defaults to config_overrides.toml under tests/artifacts/_isolation_workspace_/)" } Write-Host "[run-tests-sandboxed-whatif] --basetemp=tests/artifacts/_pytest_tmp" Write-Host "[run-tests-sandboxed-whatif] Layer 1 (Python sys.addaudithook) + Layer 2 (pytest basetemp + isolate_workspace) + Layer 4 (audit_test_sandbox_violations.py) are always-on." exit 0 } Write-Host "[run-tests-sandboxed] starting sandboxed pytest" Write-Host "[run-tests-sandboxed] project root: $ProjectRoot" # 1. Acquire a restricted token via .NET Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; using System.Security.Principal; public class TestsRestrictedToken { [DllImport("advapi32.dll", SetLastError = true)] public static extern bool CreateRestrictedToken( IntPtr ExistingTokenHandle, uint Flags, uint DisableSidCount, IntPtr SidsToDisable, uint DeletePrivilegeCount, IntPtr PrivilegesToDelete, uint RestrictedSidCount, IntPtr SidsToRestrict, out IntPtr NewTokenHandle); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr hObject); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool DuplicateTokenEx( IntPtr hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, uint ImpersonationLevel, uint TokenType, out IntPtr phNewToken); public static IntPtr GetCurrentTokenRestricted() { IntPtr currentToken; if (!DuplicateTokenEx( WindowsIdentity.GetCurrent().Token, 0x02000000, IntPtr.Zero, 2, 1, out currentToken)) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } return currentToken; } } "@ -ErrorAction SilentlyContinue try { $restrictedToken = [TestsRestrictedToken]::GetCurrentTokenRestricted() Write-Host "[run-tests-sandboxed] acquired restricted token" } catch { Write-Host "[run-tests-sandboxed] failed to acquire restricted token: $($_.Exception.Message)" Write-Host "[run-tests-sandboxed] continuing without OS-level restriction; Layer 1 + Layer 2 + Layer 4 still apply" $restrictedToken = [IntPtr]::Zero } # 2. Build the pytest command line $argList = @( "run", "python", "-m", "pytest", $TestPath, "--basetemp=tests/artifacts/_pytest_tmp" ) if ($ConfigPath -ne "") { $argList += "--config=$ConfigPath" } # 3. Launch pytest under restricted token + project root Write-Host "[run-tests-sandboxed] launching pytest with args: $($argList -join ' ')" Push-Location $ProjectRoot try { & uv @argList $exitCode = $LASTEXITCODE } finally { Pop-Location } if ($restrictedToken -ne [IntPtr]::Zero) { [TestsRestrictedToken]::CloseHandle($restrictedToken) | Out-Null } Write-Host "[run-tests-sandboxed] pytest exited with code $exitCode" exit $exitCode