agent-Specialization/scripts/setup-wsl-sandbox.ps1
JOJO 42cd99d2d8 feat(windows): WSL2 沙箱执行环境与执行环境提示词平台拆分
- Windows 宿主机模式基于 WSL2 实现沙箱执行:只读/批准/自动审核识别、
  工作区可写+区外只读挂载、网络档位(受限/开放/禁止)、敏感目录屏蔽
- 新增 scripts/setup-wsl-sandbox.ps1 一键准备 WSL 沙箱发行版
- 执行环境提示词按平台拆分骨架:prompts/execution_mode/macos.txt
  (原 execution_mode.txt,mac/dockerweb 沿用)与 windows.txt
  (骨架+动态注入环境与路径、当前规则、网络档位、切换一致性说明)
- Windows 执行环境切换通知改为完整命令写法说明(双向),mac 保持原样
- 附调研与 PoC 验证报告:wsl2-sandbox-research.md、
  windows-sandbox-research.md、wsl2-sandbox-poc-report.md
2026-07-30 13:06:34 +08:00

84 lines
4.3 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# setup-wsl-sandbox.ps1 — 创建 astrion WSL2+bwrap 专用沙箱发行版
#
# 用法PowerShell普通用户即可无需管理员
# powershell -ExecutionPolicy Bypass -File scripts\setup-wsl-sandbox.ps1
# 可选参数:
# -DistroName 发行版名称(默认 astrion-sandbox需与 HOST_SANDBOX_WSL_DISTRO 一致)
# -InstallDir 发行版 VHDX 安装目录(默认 ~\.astrion\wsl-sandbox
# -RootfsUrl Alpine minirootfs 下载地址(默认阿里云镜像)
# -ApkMirror apk 软件源镜像(默认阿里云)
#
# 设计依据wsl2-sandbox-poc-report.md
# - 必须是专用发行版并关闭 interop否则沙箱内可经 cmd.exe 逃逸到宿主机;
# - 固化公共 DNS规避 localhost 代理导致的 WSL NAT DNS 失效;
# - 内置国内 apk 镜像,避免官方源大包下载卡死。
param(
[string]$DistroName = "astrion-sandbox",
[string]$InstallDir = (Join-Path $env:USERPROFILE ".astrion\wsl-sandbox"),
[string]$RootfsUrl = "https://mirrors.aliyun.com/alpine/v3.21/releases/x86_64/alpine-minirootfs-3.21.3-x86_64.tar.gz",
[string]$ApkMirror = "https://mirrors.aliyun.com/alpine/v3.21"
)
$ErrorActionPreference = "Stop"
$env:WSL_UTF8 = "1"
function Invoke-Wsl {
param([Parameter(ValueFromRemainingArguments=$true)][string[]]$Args)
$output = & wsl.exe @Args 2>&1 | Where-Object { $_ -notmatch "localhost 代理|localhost proxy" }
return @{ Code = $LASTEXITCODE; Output = ($output -join "`n") }
}
Write-Host "==> [1/6] 检查 WSL 环境"
$null = Invoke-Wsl --status
if ($LASTEXITCODE -ne 0) {
throw "WSL 不可用。请先启用 WSL2wsl --install --no-distribution 或安装 Docker Desktop 后重试)。"
}
Write-Host "==> [2/6] 检查发行版 '$DistroName' 是否已存在"
$probe = Invoke-Wsl -d $DistroName -e true
if ($probe.Code -eq 0) {
Write-Host " 发行版已存在跳过导入如需重建wsl --unregister $DistroName"
} else {
Write-Host "==> [3/6] 下载 Alpine rootfs"
$rootfs = Join-Path $env:TEMP "astrion-alpine-minirootfs.tar.gz"
if (-not (Test-Path $rootfs)) {
Invoke-WebRequest -Uri $RootfsUrl -OutFile $rootfs -UseBasicParsing
}
Write-Host " rootfs: $rootfs ($([math]::Round((Get-Item $rootfs).Length/1MB,1)) MB)"
Write-Host "==> [4/6] 导入为 WSL2 发行版"
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
$null = Invoke-Wsl --import $DistroName $InstallDir $rootfs --version 2
$check = Invoke-Wsl -d $DistroName -e true
if ($check.Code -ne 0) { throw "发行版导入失败: $($check.Output)" }
}
Write-Host "==> [5/6] 写入沙箱配置(关闭 interop / 固定 DNS / 国内镜像)"
# 关闭 Windows 互操作:防止沙箱内经 cmd.exe 逃逸宿主机PoC 已验证该逃逸路径)
$null = Invoke-Wsl -d $DistroName -- sh -c "printf '[network]\ngenerateResolvConf = false\n\n[interop]\nenabled = false\nappendWindowsPath = false\n' > /etc/wsl.conf"
$null = Invoke-Wsl -d $DistroName -- sh -c "rm -f /etc/resolv.conf && printf 'nameserver 223.5.5.5\nnameserver 119.29.29.29\n' > /etc/resolv.conf"
$null = Invoke-Wsl -d $DistroName -- sh -c "printf '$ApkMirror/main\n$ApkMirror/community\n' > /etc/apk/repositories"
# 使 wsl.conf 生效
$null = Invoke-Wsl --terminate $DistroName
Start-Sleep -Seconds 2
Write-Host "==> [6/6] 安装沙箱工具链bubblewrap / bash / python3 / git"
$apk = Invoke-Wsl -d $DistroName -- sh -c "apk update && apk add bubblewrap bash ncurses-libs python3 git"
if ($apk.Code -ne 0) { throw "apk 安装失败: $($apk.Output)" }
# 验收
$verify = Invoke-Wsl -d $DistroName -- sh -c "bwrap --version && bash -c 'echo bash-ok' && python3 --version && git --version"
Write-Host $verify.Output
$escape = Invoke-Wsl -d $DistroName -- bwrap --die-with-parent --new-session --unshare-all --ro-bind / / --proc /proc --dev /dev -- bash -c "cmd.exe /c echo escape 2>&1 || echo interop-blocked"
if ($escape.Output -match "interop-blocked|not found") {
Write-Host " interop 逃逸封堵验证: OK"
} else {
Write-Warning " interop 可能未关闭,请检查 /etc/wsl.conf 后执行 wsl --terminate $DistroName"
}
Write-Host ""
Write-Host "完成。沙箱发行版 '$DistroName' 就绪。"
Write-Host "若使用了非默认名称,请设置环境变量 HOST_SANDBOX_WSL_DISTRO=$DistroName"