fix(powershell): sec deny powershell encoding bypass via iex injection.

This commit is contained in:
sky5454 2026-05-10 02:12:14 +08:00
parent 6e6293e596
commit a75ed069f4
2 changed files with 46 additions and 0 deletions

View file

@ -95,6 +95,14 @@ var (
regexp.MustCompile(`\bssh\b.*@`), regexp.MustCompile(`\bssh\b.*@`),
regexp.MustCompile(`\beval\b`), regexp.MustCompile(`\beval\b`),
regexp.MustCompile(`\bsource\s+.*\.sh\b`), regexp.MustCompile(`\bsource\s+.*\.sh\b`),
// PowerShell encoding bypass: [Text.Encoding] used to construct command strings.
regexp.MustCompile(`\[text\.encoding\]`),
// PowerShell -EncodedCommand flag (base64-encoded command).
regexp.MustCompile(`-encodedcommand`),
// .GetString called on byte array to decode commands.
regexp.MustCompile(`\.getstring\(\[byte\[\]`),
// FromBase64String used in command construction chain.
regexp.MustCompile(`frombase64string\(`),
} }
// absolutePathPattern matches absolute file paths in commands (Unix and Windows). // absolutePathPattern matches absolute file paths in commands (Unix and Windows).

View file

@ -703,6 +703,44 @@ func TestShellTool_URLBypassPrevented(t *testing.T) {
} }
} }
// TestShellTool_PowerShellEncodingBypass verifies that PowerShell encoding bypass techniques are blocked.
func TestShellTool_PowerShellEncodingBypass(t *testing.T) {
tool, err := NewExecTool("", false)
require.NoError(t, err)
ctx := context.Background()
// Commands using [Text.Encoding] to construct a command string at runtime.
encodingBypassCommands := []string{
`[Text.Encoding]::ASCII.GetString([byte[]](0x6c,0x73,0x20,0x7e))`,
`[Text.Encoding]::ASCII.GetString([byte[]](0x69,0x65,0x78))`,
`[System.Text.Encoding]::ASCII.GetString([byte[]](0x69,0x65,0x78))`,
}
for _, cmd := range encodingBypassCommands {
result := tool.Execute(ctx, map[string]any{"action": "run", "command": cmd})
if !result.IsError {
t.Errorf("expected [Text.Encoding] bypass to be blocked: %s", cmd)
}
if !strings.Contains(result.ForLLM, "blocked") && !strings.Contains(result.ForUser, "blocked") {
t.Errorf("expected 'blocked' message for %s, got: %s", cmd, result.ForLLM)
}
}
// Commands using PowerShell's -EncodedCommand flag (base64).
encodedCommands := []string{
`powershell -NoProfile -NonInteractive -EncodedCommand SQBFAHIAaABlAGwAbAAvAC8A`,
`pwsh -EncodedCommand aWV4`,
}
for _, cmd := range encodedCommands {
result := tool.Execute(ctx, map[string]any{"action": "run", "command": cmd})
if !result.IsError {
t.Errorf("expected -EncodedCommand to be blocked: %s", cmd)
}
}
}
func TestShellTool_Background_ReturnsImmediately(t *testing.T) { func TestShellTool_Background_ReturnsImmediately(t *testing.T) {
tool, err := NewExecTool("", false) tool, err := NewExecTool("", false)
require.NoError(t, err) require.NoError(t, err)