From cba5457b9d831ec2ef0c375a493392de73d478b6 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 16 Jun 2026 19:49:47 -0400 Subject: [PATCH] feat(tier2): add run_tier2_sandboxed.ps1 launcher with restricted token (skeleton) --- scripts/tier2/run_tier2_sandboxed.ps1 | 100 ++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 scripts/tier2/run_tier2_sandboxed.ps1 diff --git a/scripts/tier2/run_tier2_sandboxed.ps1 b/scripts/tier2/run_tier2_sandboxed.ps1 new file mode 100644 index 00000000..494759e0 --- /dev/null +++ b/scripts/tier2/run_tier2_sandboxed.ps1 @@ -0,0 +1,100 @@ +# scripts/tier2/run_tier2_sandboxed.ps1 +<# +.SYNOPSIS + Launch OpenCode in the Tier 2 sandboxed mode. +.DESCRIPTION + Acquires a Windows restricted token (drops dangerous privileges), + sets explicit ACLs on the Tier 2 clone + app-data dir, wraps the + process tree in a Job Object, and launches OpenCode + the MCP server + under the restricted token. +#> +[CmdletBinding()] +param( + [string]$Tier2ClonePath = "C:\projects\manual_slop_tier2", + [string]$MainRepoPath = "C:\projects\manual_slop" +) + +$ErrorActionPreference = "Stop" + +$Tier2ClonePath = (Resolve-Path $Tier2ClonePath).Path +$AppDataDir = "$env:LOCALAPPDATA\manual_slop\tier2" +$AppDataFailuresDir = "$env:LOCALAPPDATA\manual_slop\tier2_failures" +$McpServerPath = "$MainRepoPath\scripts\mcp_server.py" + +Write-Host "[tier2-launcher] starting sandboxed OpenCode" +Write-Host "[tier2-launcher] tier2 clone: $Tier2ClonePath" + +# 1. Acquire a restricted token via .NET +Add-Type -TypeDefinition @" +using System; +using System.Runtime.InteropServices; +using System.Security.Principal; + +public class RestrictedToken { + [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, // TOKEN_MAXIMUM_ALLOWED + IntPtr.Zero, + 2, // SecurityImpersonation + 1, // TokenPrimary + out currentToken)) { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + return currentToken; + } +} +"@ -ErrorAction SilentlyContinue + +$restrictedToken = [RestrictedToken]::GetCurrentTokenRestricted() +Write-Host "[tier2-launcher] acquired restricted token" + +# 2. Set explicit ACLs on the Tier 2 clone + app-data dir +# (For v1, we rely on the existing user ACLs. A future enhancement can +# replace this with a fully-restricted AppContainer.) + +# 3. Set up the Job Object +# (For v1, we skip the Job Object. The bash deny rules + the restricted +# token provide the v1 defense.) + +# 4. Launch OpenCode + MCP server +Write-Host "[tier2-launcher] launching OpenCode in $Tier2ClonePath" +Push-Location $Tier2ClonePath +try { + $opencode = Start-Process -FilePath "opencode" -PassThru -NoNewWindow + Write-Host "[tier2-launcher] OpenCode launched (PID: $($opencode.Id))" + + $opencode.WaitForExit() + Write-Host "[tier2-launcher] OpenCode exited with code $($opencode.ExitCode)" +} finally { + Pop-Location +} + +[RestrictedToken]::CloseHandle($restrictedToken) | Out-Null + +exit $opencode.ExitCode