Skip to content

fix(shell): unescape backslash-escaped chars in bash path args - #49691

Closed
holny wants to merge 1 commit into
anomalyco:devfrom
holny:fix-49671-shell-unescape
Closed

holny wants to merge 1 commit into
anomalyco:devfrom
holny:fix-49671-shell-unescape

Conversation

@holny

@holny holny commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #49671

Type of change

  • Bug fix

What does this PR do?

The shell tool's bash branch only unquote()s raw args, which is a no-op for unquoted words with backslash-escaped characters (/tmp/my\ project/x keeps the \). So resolvePath gets the literal string, containsPath misses, and the path looks "external" — triggering the external_directory prompt and, under a "*": deny agent rule, hard-denying the command.

Adds an unescape pass (\X → X) after unquote() in the bash branch of argPath so escaped characters collapse before path.resolve. The PowerShell branch is unchanged (its expand() chain already strips them).

How did you verify your code works?

  • test/tool/shell.test.ts regression test: project root itself contains a space, inner cat <root>/x.txt uses \ escaping → asserts external_directory is not triggered, exit 0, output contains "ok"
  • shell.test.ts 24/24 pass (23 baseline + 1 regression)
  • bun run typecheck clean

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

argPath in the bash branch only ran unquote() on raw args, which is a no-op
for unquoted words with backslash-escaped chars (`/tmp/my\ project/x` keeps
the literal backslash). The resolved path then literalises the backslash and
path.relative() reports it as outside the project root when the project
itself contains spaces, so the tool wrongly asks for external_directory
permission (or hard-denies under a "*": "deny" agent rule).

Strip backslash-escape sequences after unquote() so escaped chars collapse
before path.resolve. PowerShell already handles this via expand(), so the
fix is scoped to the bash branch.

Closes anomalyco#49671
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@holny

holny commented Sep 26, 2026

Copy link
Copy Markdown
Contributor Author

Gentle nudge on this one — it's been open for a week with green checks and no review yet. The fix is small (one unescape pass in the bash path + one regression test), and the original misfire only bites when the project root itself contains a space. Happy to rebase or adjust if anything's off.

@kvnloo

kvnloo commented Sep 28, 2026

Copy link
Copy Markdown

A backslash-escaped space in a bash path arg is left escaped, so an in-project path whose root contains a space is treated as external.

Head 1c0ad219fad94ab01435ab68ad758a804bd9c73b is unchanged from the tested tip.

Fork leaf kvnloo#199 recorded fail→pass on packages/opencode/test/tool/shell.test.ts (24 pass, 1 fail with the assertion removed, 24 pass after restore).

That locks the unescape pass for bash path args. It does not change non-path shell parsing.

@thdxr

thdxr commented Oct 10, 2026

Copy link
Copy Markdown
Member

This branch has been upgraded to V2. We're no longer taking PRs for V1. If you think this is still relevant, please port it over and open it for V2.

— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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.

bash tool: backslash-escaped spaces make in-project paths look external (external_directory prompt / hard deny under "*": deny)

3 participants