[BUG] bash tool executes environment variable contents when newlines are included
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Version: 2.1.251
OS: macOS 25.5.0 (darwin). Shell: zsh. Terminal: GhosTTY
Related: #85447, #83243, #83871.
Description
The Bash tool caches environment variable state that is then prepended to bash tool call commands. The tool writes each variable as an unquoted NAME=value line. The user command is on the last line.
The environment state is output to bash without being properly quoted or escaped, so environment variable values with line breaks executes partial contents of the environment variable.
This can cause the tool to fail, or cause spurious errors to be output. Since environment variables can contain any shell code, it also means that it can silently execute an unintended side effect.
Effect
- The shell shows a parse error on every shell call. Command may not be executed.
- The shell does not get the full environment. The assignments do not run.
- The shell runs the additional lines of a multi-line value as commands. This is a command injection.
Evidence
I recorded $ZSH_EXECUTION_STRING from ~/.zshenv to get the generated script. I removed the secret values.
export TMPPREFIX=/tmp/claude/zsh
PROJECT_DIR=/path/to/project
...
JWT_JWKS_STATIC={
"keys": [
{
"use": "sig",
"kty": "RSA"
}
]
}
...
: && setopt NO_EXTENDED_GLOB NO_BARE_GLOB_QUAL 2>/dev/null || true && ... && eval 'echo 0' < /dev/null && pwd -P >| /tmp/claude-<uid>/cwd-<pid>
The shell reads JWT_JWKS_STATIC={ as the start of a command group. The shell then fails at the closing brace on line 57. The user command is on line 70. The shell does not run it.
direnv set this variable from a project .envrc file. A PEM key in the environment corrupts the preamble in the same way. A PEM key holds no braces, thus the shell gives command not found messages instead of a parse error.
What Should Happen?
When escaped properly, environment variables of any value should be consumed properly by the shell and not partially executed.
Error Messages/Logs
The error written depends a lot on what's in the environment variable as the injected code is executed.
This can be something like
zsh:57: parse error near `}'
But many other messages are possible.
Steps to Reproduce
How to repeat the fault
- Set an environment variable that holds a newline and braces:
``sh``
export FOO=$'a{\nb\n}'
- Start Claude Code.
- Run any Bash tool call. The call fails (or shows an error).
You can also put these lines in a project .envrc file:
export JWT_JWKS_STATIC='{
"keys": []
}'
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
Somewhere in the 2.1.210+ range I think
Claude Code Version
2.1.251
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
Closes #85424 which was previously opened by Claude but didn't properly follow the template and seemed to be languishing untriaged.