Skip to content

Fix PowerShell injection in Windows tool helpers - #34

Merged
kriserickson merged 3 commits into
tool-callingfrom
copilot/sub-pr-28-again
Mar 1, 2026
Merged

kriserickson merged 3 commits into
tool-callingfrom
copilot/sub-pr-28-again

Conversation

Copilot AI commented Mar 1, 2026 •

Copy link
Copy Markdown
Contributor

execCommandHelp and execCheckCommand on Windows interpolated model-supplied input directly into PowerShell -Command strings, enabling arbitrary PowerShell injection.

Changes

  • execCommandHelp: Replace fmt.Sprintf("Get-Help '%s'", command) with a static script referencing $env:HELP_COMMAND; pass the value via cmd.Env.
  • execCheckCommand: Same pattern — replace fmt.Sprintf("Get-Command '%s'", command) with $env:CHECK_COMMAND set in the process environment.
// Before
cmd := exec.CommandContext(ctx, "powershell", "-Command", fmt.Sprintf("Get-Help '%s'", command))

// After
cmd := exec.CommandContext(ctx, "powershell", "-Command", "Get-Help -Name $env:HELP_COMMAND")
cmd.Env = append(os.Environ(), "HELP_COMMAND="+command)

The command name is now passed out-of-band through the process environment, never interpolated into the script string.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…indows

Co-authored-by: kriserickson <325934+kriserickson@users.noreply.github.com>
Copilot AI changed the title [WIP] WIP Address feedback on Tool calling pull request Fix PowerShell injection in Windows tool helpers Mar 1, 2026
@kriserickson
kriserickson marked this pull request as ready for review March 1, 2026 20:05
Copilot AI review requested due to automatic review settings March 1, 2026 20:05
@kriserickson
kriserickson merged commit 30261c1 into tool-calling Mar 1, 2026
0 of 2 checks passed
@kriserickson
kriserickson deleted the copilot/sub-pr-28-again branch March 1, 2026 20:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a PowerShell command-injection vulnerability on Windows by removing direct interpolation of model-supplied command names into powershell -Command strings and instead passing the values out-of-band via environment variables.

Changes:

  • Update execCommandHelp (Windows) to reference $env:HELP_COMMAND instead of fmt.Sprintf(...) interpolation.
  • Update execCheckCommand (Windows) to reference $env:CHECK_COMMAND instead of fmt.Sprintf(...) interpolation.
Comments suppressed due to low confidence (3)

internal/tools/tools.go:152

  • There is still a PowerShell injection vector on Windows via execListDirectory: it builds -Command with fmt.Sprintf("Get-ChildItem '%s'", absPath) (tools.go:107). ValidatePath constrains traversal but does not prevent ' / ; etc in the path, so model-supplied path can still break out of the quoted string and execute arbitrary PowerShell. Consider applying the same out-of-band parameter pattern here as well (e.g., pass the path via env var and use -LiteralPath in the script, or otherwise avoid string interpolation in -Command).
	if info.IsDir() {
		return "", fmt.Errorf("%q is a directory, not a file", path)

internal/tools/tools.go:152

  • The new Windows-specific injection mitigation in execCommandHelp isn’t covered by tests (existing tests skip Windows success paths), so regressions back to string interpolation could slip in unnoticed. Consider refactoring to separate “build the exec.Cmd” from “run it”, or injecting an execCommandContext function, so unit tests can assert the PowerShell arguments and that cmd.Env is used to pass the command name.
	if info.IsDir() {
		return "", fmt.Errorf("%q is a directory, not a file", path)

internal/tools/tools.go:260

  • execCheckCommand also changed to pass the command name via cmd.Env, but there’s no test coverage asserting the Windows code path uses environment variables (and not fmt.Sprintf interpolation). If you refactor to make command construction testable, add a focused unit test for this function too to prevent reintroducing PowerShell -Command injection.
}


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants