[BUG] Bash tool escaping broken when text includes `<`
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: 1.0.35
- Operating System: NixOS
- Terminal: alacritty, fish
Bug Description
<!-- A clear and concise description of the bug -->
When Claude executes any code including <, it will incorrectly include a reference to /dev/null, probably an escaping issue.
e.g. here’s claude trying to execute
● Bash(./debug_stdin_c < /tmp/test_simple.ne)
⎿ Calling read() syscall on stdin (fd 0)...
Read 0 bytes (EOF)
And here’s what strace says it’s actually running:
execve("/nix/store/94lg0shvsfc845zy8gnflvpqxxiyijbz-bash-interactive-5.2p37/bin/bash", ["/nix/store/94lg0shvsfc845zy8gnflvpqxxiyijbz-bash-interactive-5.2p37/bin/bash", "-c", "-l", "source /tmp/claude-shell-snapshot-b545 && eval './debug_stdin_c < /tmp/test_simple.ne' \\< /dev/null && pwd -P >| /tmp/claude-c497-cwd"], 0x3a06e070 / 166 vars /) = 0
Another example to show that it even breaks with inner string <:
● Bash(echo '<4:name|t5:Alice,' | ./result/bin/netencode-pretty)
⎿ Error: netencode-pretty: unable to parse netencode from stdin: Parse error at: '<4:name < /dev/null | t5:Alice,
' (kind: Tag)
execve("/nix/store/94lg0shvsfc845zy8gnflvpqxxiyijbz-bash-interactive-5.2p37/bin/bash", ["/nix/store/94lg0shvsfc845zy8gnflvpqxxiyijbz-bash-interactive-5.2p37/bin/bash", "-c", "-l", "source /tmp/claude-shell-snapshot-b545 && eval \"echo '<4:name\" \\< /dev/null \\| \"t5:Alice,' | ./result/bin/netencode-pretty\" && pwd -P >| /tmp/claude-77cd-cwd"], 0x396ee030 / 166 vars /) = 0
As expected it gets majorly confused by that result and starts flailing wildly.
Steps to Reproduce
Try to make claude run anything that contains a <, e.g. ask it to pipe a string containing < into hexdump, it will include garbage in the dump.
Interestingly enough, it seems to work for simple cases:
● Bash(echo '<' | hexdump -C)
⎿ 00000000 3c 0a |<.|
00000002
● That works fine - we get 3c (ASCII for <) followed by 0a (newline). So basic < character handling works. The issue was with shell redirection when using < filename, not with
the < character itself.
> Hm, what about a netencode value like above?
● Bash(echo '<4:name|t5:Alice,' | hexdump -C)
⎿ 00000000 3c 34 3a 6e 61 6d 65 20 3c 20 2f 64 65 76 2f 6e |<4:name < /dev/n|
00000010 75 6c 6c 20 7c 20 74 35 3a 41 6c 69 63 65 2c 0a |ull | t5:Alice,.|
00000020
● Ah! There's the problem! The shell is interpreting the | as a pipe and redirecting from /dev/null. Looking at the hex dump:
- 3c 34 3a 6e 61 6d 65 = <4:name
- 20 3c 20 2f 64 65 76 2f 6e 75 6c 6c 20 = < /dev/null
- 7c 20 74 35 3a 41 6c 69 63 65 2c = | t5:Alice,
The shell is treating <4:name|t5:Alice, as <4:name with input redirected from /dev/null piped to t5:Alice,. That's why we're getting the parse error - the actual input
contains the shell redirection artifacts.
We need to escape or quote the netencode string to prevent shell interpretation.
Expected Behavior
Any character should be passed through to bash as claude wants to.
Actual Behavior
See above
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗