Repository navigation
[Windows] pwsh tool always fails with "PTY shell exited during startup" under workspace-write / read-only
#12115
Replies: 4 comments 1 reply
|
Hi! The minimal token-flag reproduction provides strong evidence that the failure happens before PowerShell processes any commands. I would recommend treating this as a sandbox compatibility issue, not as a PowerShell installation problem. Before changing the restricted-token flags, I would add an automated Windows test matrix covering:
The test should verify both successful process initialization and enforcement of the intended restrictions. Removing Until a validated fix exists, the UI should report a sandbox initialization failure rather than misleading users with a generic PTY shell error. |
|
补充:这类 PTY 启动失败可能是两层故障叠在一起(2026-11-05 新环境复现) 重装系统后换了一个全新工作目录,同一条 Win32 5 = 也就是说,在「pwsh 起不来」前面还有一道门:dsh 要修改工作目录的 DACL,而当前用户对这个目录没有「修改权限」的权限。 给目录补一条显式 Full 之后(管理员 PowerShell): icacls "<工作目录>" /grant "<用户>:(OI)(CI)F" /T /C(PowerShell 下权限串必须整体加引号,否则 授权生效后, 也就是 两点建议
环境:Windows 11 24H2(10.0.26100.9703),dsh 0.2.1-rc.5,pwsh 7.6.9(GitHub MSI 版,非商店版别名)。 |
|
I'm seeing the same error on a Linux system that does not sport I'd like to see a better error instead that detailed the shell used and raised the underlying errors. Maybe the standard |
Follow-up: the PTY child that dies is the sandbox runner, not the shellWe reproduced this on DSH Desktop 0.2.2-rc.1 (Electron 44.7.0 / Node 24.21.0, Windows 11 x64, The process that exits is the ACL runner. With confinement, What we measured (probes run outside the sandbox, because ConPTY allocation itself fails with
Reading of the results. Under ConPTY only console-subsystem children are attached to the pseudoconsole and receive its standard handles; a GUI-subsystem child (the Electron executable) gets none, so the runner cannot inherit or create the shell's stdio and fails before spawning it. This explains why |
Uh oh!
There was an error while loading. Please reload this page.
Summary
On Windows, the
pwshtool is unusable in any sandbox mode exceptdanger-full-access. Every call fails with:Root cause is not PowerShell.
sandbox.confine()wraps the shell in a restricted token created withWRITE_RESTRICTED, and PowerShell 7 / Windows PowerShell 5.1 /node.exeall fail DLL initialization (0xC0000142=STATUS_DLL_INIT_FAILED) under that token.cmd.exeandpython.exeare unaffected.Environment
@deepseek-ai/dsh-desktop0.2.1-rc.5(Electron 44.7.0, Node 24.21.0)10.0.26100.9703, x64C:\Program Files\PowerShell\7\pwsh.exeworkspace-write(also reproducible inread-only)Steps to reproduce
workspace-write.pwshtool with any command, e.g.echo hi.Error: PTY shell exited during startup.danger-full-access— the same call succeeds immediately.The failure happens at shell startup, before any command is sent:
startupSession()sendsENCODING_PREAMBLE + PWSH_PROMPT_SETUPas the first input and getswaitReason === "session_exit".Workaround currently in use
The only way to get a working shell on this machine is to keep the session in
danger-full-access. That is not a real workaround —danger-full-accessdisables the sandbox entirely, so the trade is "no shell at all" versus "no sandbox at all". In practice we run the session unsandboxed just to be able to run commands.We also wasted a long time on this because the error message points somewhere else entirely: we first assumed PowerShell was not installed, then that the
pwshinPATHwas a broken Microsoft Store alias, then that ConPTY /conpty.dllwas at fault. We installed PowerShell 7 (MSIX, then MSI), removed the Store build, restarted the app several times and rebooted the machine — none of it mattered. The sandboxed spawn was failing the whole time, and the error surfaced as a shell exit.Root cause
spawnArgv()in the terminal backend only bypasses confinement fordanger-full-access:On Windows the only runner is
windows-acl(PLATFORM_CHAINS.win32 = ["windows-acl"], selected without a probe;STATIC_ENFORCEMENT["windows-acl"] = "partial"). It spawns the command through a restricted token built in@deepseek-ai/dsh-sandbox-windows-acl:13 = DISABLE_MAX_PRIVILEGE(1) | LUA_TOKEN(4) | WRITE_RESTRICTED(8).Evidence — minimal P/Invoke reproduction
Standalone script using
OpenProcessToken+CreateRestrictedToken+CreateProcessAsUserW(no admin rights needed), spawningpwsh -NoLogo -NoProfile -Command "exit 42":Same token (
flags=13) applied to different binaries:cmd.exe /c exit 47python.exe -c "sys.exit(46)"node.exe -e "process.exit(45)"powershell.exe(Windows PowerShell 5.1)pwsh.exe(PowerShell 7.x)So the trigger is
WRITE_RESTRICTEDalone — low integrity level and the choice of restricting SID make no difference.Possible directions
These are open questions rather than proposals — the first one in particular touches the security model, and I don't have enough context to judge whether it is safe. Treat them as input for whatever direction you'd prefer.
WRITE_RESTRICTEDstill needed for this spawn? Spawning withflags = 5(dropping onlyWRITE_RESTRICTED) works, and the capability-SID DACL grants plus the low integrity label are still applied on top. If those two are considered sufficient by themselves, this would resolve the failure. IfWRITE_RESTRICTEDis load-bearing here, then perhaps it could be scoped to commands that don't need to initialise a large runtime — though I don't have enough context on the threat model to judge whether that is safe.probeRunner? Todaywin32has a single candidate that is never probed, so a broken configuration is selected unconditionally. A real probe (spawncmd /c exit 0and apwsh -NoProfile -Command exit 0smoke test) would surface this as a cleanSandboxUnavailableErrorinstead of a misleading shell error.0xC0000142from the confined spawn degrade gracefully, instead of being reported as a shell exit?Error mapping note
A failed
spawnsurfaces aswaitReason === "session_exit"→throw new Error("PTY shell exited during startup"), which hides the actualSTATUS_DLL_INIT_FAILED. Distinguishing "the process could not start" from "the shell exited" would make this far faster to diagnose.All reactions