Windows: execute string commands with PowerShell 7 - #37
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a Windows-specific shell execution contract so Windows string commands are executed via server-resolved PowerShell 7 (pwsh.exe) rather than falling back to cmd.exe, and extends safe-mode policy checks to recognize common PowerShell network/destructive patterns. It also adds Windows CI/test coverage and updates operator-facing documentation, while synchronizing uv.lock metadata.
Changes:
- Add trusted
pwsh.exeresolution (with optional operator pinning) and use it for Windowsshell=Truestring commands. - Extend safe-mode command policy scanning to detect PowerShell network cmdlets and recursive deletion aliases/abbreviations.
- Add Windows PowerShell execution tests, update docs, and run the new tests in Windows CI; update
uv.lockfor0.2.2andpyyaml.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
coding_tools_mcp/processes.py |
Resolves pwsh.exe from trusted server environment, verifies PS major version, and uses PowerShell 7 for Windows string commands. |
coding_tools_mcp/server.py |
Adds PowerShell-focused regexes to block network/destructive commands in safe mode. |
tests/test_windows_pwsh.py |
Adds unit/integration tests for pwsh resolution/spawning and safe-mode policy enforcement. |
.github/workflows/compliance.yml |
Runs the new Windows PowerShell tests in the Windows compliance workflow. |
README.md |
Documents Windows string-command behavior, error codes, and the PowerShell 7 contract. |
docs/runtime-contract-v0.2.md |
Adds SHELL_NOT_FOUND / SHELL_VERSION_UNSUPPORTED to documented error codes. |
docs/limitations.md |
Documents Windows PowerShell 7 requirement and lack of cmd.exe fallback. |
uv.lock |
Bumps project version metadata and adds pyyaml to the dev extra lock content. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| POWERSHELL_NETWORK_RE = re.compile( | ||
| r"(?:^|[;&|{}\r\n])\s*(?:Invoke-WebRequest|Invoke-RestMethod|Start-BitsTransfer|" | ||
| r"Test-NetConnection|Test-Connection|Resolve-DnsName|iwr|irm|tnc|ping(?:\.exe)?|" | ||
| r"nslookup(?:\.exe)?|tracert(?:\.exe)?)\b|(?:System\.)?Net\.", |
|
PowerShell 让 safe mode 的网络/破坏性命令检查可以被绕过。 $c='Invoke-WebRequest'; & $c example.com 第一条可绕过 network gate,第二条可绕过 recursive deletion gate。对应执行切 PowerShell 的位置在 coding_tools_mcp/processes.py:221-224。 |
Summary
This is the first layer of the Windows runtime work tracked in #36 and is intentionally based on #34 (
fix/sessionless-process-runs). PR #34 already provides workspace-scoped command handles; this layer adds the Windows shell contract without duplicating that registry.pwsh.exe)cmd.exeCODING_TOOLS_MCP_PWSH_PATHuv.lockwith the0.2.2/ PyYAML metadata already present on the base branchSecurity properties
The request environment cannot choose the shell executable. Resolution uses only the server process environment or the explicit absolute operator setting. The spawned shell runs with
-NoLogo -NoProfile -NonInteractive.Validation
On Windows 11 with PowerShell 7 and Python 3.13:
uv lock --check: passStack
GitHub's stacked-PR preview does not support cross-fork stacks, so the official two-layer stack is hosted in the contributor fork:
The second layer contains only Windows environment normalization, portable fixtures/cleanup, and static typing fixes. It can be retargeted upstream after this layer lands or if the branches are adopted into upstream.