Skip to content

Commit adad0ca

Browse files
author
SqlRush
committed
Preserve native PowerShell alias collisions
1 parent 02680ad commit adad0ca

4 files changed

Lines changed: 29 additions & 8 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ M5 补充:PowerShell read-only classifier 现在覆盖 `Get-FileHash` 的安
211211

212212
M5 补充:PowerShell read-only classifier 继续覆盖 Windows `certutil -hashfile <path> [algorithm]` 的安全相对路径 checksum 形态,同时拒绝 `certutil` 其它子命令、pass-through、越界路径、动态算法和额外参数。
213213

214+
M5 补充:PowerShell command canonicalization 现在保留与 PowerShell alias 碰撞的 `.exe`/`.cmd`/`.bat`/`.com` 原生命令名,避免 `fc.exe``sort.exe``sc.exe` 等被误当成 `Format-Custom``Sort-Object``Set-Content` 分类。
215+
214216
M5 补充:Bash 前台输出和 `BashOutput` 现在都走统一 tool-result budget 截断/落盘路径;`BashOutput` 增加 100k 最大结果限制,大后台输出会保存完整内容并返回 `full_output_path` 元数据。
215217

216218
M5 补充:Bash/PowerShell 后台任务现在会发 `*_background_started``*_background_finished` tool progress 事件,包含后台 ID、shell/status、exit/timed_out/cancelled、duration、时间戳和输出字节数,不携带 command 文本;completed、timed_out、cancelled 终态均已覆盖测试。

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ test/parity/ # golden tests against TS/official behavior
217217
- 本轮补充:Bash read-only classifier 现在覆盖常见 checksum 命令 `md5sum`/`sha*sum`/`b2sum`/`shasum`/`cksum`/`sum` 的普通文件读取形态,同时阻断 `-c`/`--check` 校验清单模式,避免清单内路径绕过路径权限。
218218
- 本轮补充:PowerShell read-only classifier 现在覆盖 `Get-FileHash` 的安全路径读取和常见 native checksum 命令 `md5sum`/`sha*sum`/`b2sum`/`shasum`/`cksum`/`sum`,同时拒绝 `Get-FileHash -InputStream` 表达式和 `-c`/`--check` 校验清单模式。
219219
- 本轮补充:PowerShell read-only classifier 继续覆盖 Windows `certutil -hashfile <path> [algorithm]` 的安全相对路径 checksum 形态,同时拒绝 `certutil` 其它子命令、pass-through、越界路径、动态算法和额外参数。
220+
- 本轮补充:PowerShell command canonicalization 现在保留与 PowerShell alias 碰撞的 `.exe`/`.cmd`/`.bat`/`.com` 原生命令名,避免 `fc.exe``sort.exe``sc.exe` 等被误当成 `Format-Custom``Sort-Object``Set-Content` 分类。
220221
- 本轮补充:`BashOutput` 现在设置 100k 最大结果大小,和前台 `Bash` 一起覆盖大输出 tool-result preview 截断、完整输出落盘及 `full_output_path` 元数据。
221222
- 本轮补充:Bash/PowerShell 后台命令现在会通过 tool progress 通道发 started/finished 事件,记录后台 ID、shell/status、exit/timed_out/cancelled、duration、时间戳和 stdout/stderr byte count,且 completed、timed_out、cancelled 终态测试确保 progress 不携带 command 文本。
222223
- 本轮补充:WebSearch domain filters 现在在 schema 层声明 array `items:string`,通用 tool schema validator 同步支持 `items` 校验;`allowed_domains`/`blocked_domains` 会拒绝空字符串、URL/port、非法 wildcard 和非域名 label。

internal/tools/powershell/tools.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,17 +2026,30 @@ func safeRelativePowerShellPath(path string) bool {
20262026

20272027
func canonicalCommand(command string) string {
20282028
name := strings.ToLower(strings.Trim(strings.TrimSpace(command), `"'`))
2029-
if name == "where.exe" {
2030-
return name
2031-
}
20322029
if !strings.ContainsAny(name, `/\`) {
2033-
for _, suffix := range []string{".exe", ".cmd", ".bat", ".com"} {
2034-
if strings.HasSuffix(name, suffix) {
2035-
name = strings.TrimSuffix(name, suffix)
2036-
break
2030+
if stem, ok := stripPowerShellExecutableSuffix(name); ok {
2031+
if powerShellAliasTarget(stem) != "" {
2032+
return name
20372033
}
2034+
name = stem
20382035
}
20392036
}
2037+
if target := powerShellAliasTarget(name); target != "" {
2038+
return target
2039+
}
2040+
return name
2041+
}
2042+
2043+
func stripPowerShellExecutableSuffix(name string) (string, bool) {
2044+
for _, suffix := range []string{".exe", ".cmd", ".bat", ".com"} {
2045+
if strings.HasSuffix(name, suffix) {
2046+
return strings.TrimSuffix(name, suffix), true
2047+
}
2048+
}
2049+
return name, false
2050+
}
2051+
2052+
func powerShellAliasTarget(name string) string {
20402053
switch name {
20412054
case "cat", "gc":
20422055
return "get-content"
@@ -2105,6 +2118,6 @@ func canonicalCommand(command string) string {
21052118
case "measure":
21062119
return "measure-object"
21072120
default:
2108-
return name
2121+
return ""
21092122
}
21102123
}

internal/tools/powershell/tools_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ func TestPowerShellCommandClassification(t *testing.T) {
350350
"certutil -hashfile README.md SHA256 extra",
351351
"certutil --% -hashfile README.md SHA256",
352352
"certutil -urlcache -split -f https://example.com/file out.bin",
353+
"fc.exe README.md /etc/passwd",
354+
"sort.exe /etc/passwd",
353355
"dotnet build",
354356
"dotnet --info $env:SECRET",
355357
"docker run alpine",
@@ -421,6 +423,9 @@ func TestPowerShellCommandClassification(t *testing.T) {
421423
t.Fatalf("%q should be destructive", command)
422424
}
423425
}
426+
if IsDestructiveCommand("sc.exe query") {
427+
t.Fatalf("native sc.exe should not be classified as Set-Content alias")
428+
}
424429
}
425430

426431
func TestPowerShellToolDynamicSafetyFlags(t *testing.T) {

0 commit comments

Comments
 (0)