[BUG] Bash Tool JQ Command Escaping Issue
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: 0.2.115 (Claude Code)
- Operating Systems:
- macOS Darwin 24.4.0
- Ubuntu linux
! ~/.claude/local/claude --version
⎿ 0.2.98 (Claude Code)
! lsb_release --version
⎿ LSB Version: core-11.1.0ubuntu4-noarch:printing-11.1.0ubuntu4-noarch:security-11.1.0ubuntu4-noarc
- Terminal: Command line through Claude Code
Bug Description
The Bash tool in Claude Code has a critical escaping bug that corrupts
jq commands containing the pattern .entries[]|. This pattern gets
incorrectly transformed during command preparation, causing stdin
redirection syntax (< /dev/null) to be injected into the middle of
jq expressions, resulting in syntax errors that make many common jq
queries impossible to execute.
Steps to Reproduce
- Create a JSON file with an
entriesarray structure:
``json``
{"entries": [{"title": "test"}, {"title": "example"}]}
- Execute a jq command using the Bash tool with array filtering:
``ClaudeExecStepOutput``
Bash('jq \'[.entries[]|select(.title=="test")]|length\' file.json')
- The command fails with a jq syntax error
Expected Behavior
The jq command should execute correctly and return the count of matching entries:
$ jq '[.entries[]|select(.title=="test")]|length' file.json
1
Actual Behavior
The command fails with a syntax error because the pipe character is corrupted:
jq: error: syntax error, unexpected '/' (Unix shell quoting issues?) at <top-level>, line 1:
[.entries[] < /dev/null | select(.title=="test")]|length
The pattern .entries[]| is being transformed to .entries[] < /dev/null | during command escaping.
Additional Context
Root Cause Analysis
Through testing, we discovered that the command escaping mechanism
specifically corrupts the pattern .entries[]| by inserting < between the array accessor and pipe. This can be verified
/dev/null
by base64 encoding:
# create file.json
echo '{"entries": [{"title": "test"}, {"title": "example"}]}' > file.json
# What we type:
jq '[.entries[]|select(.title=="test")]|length' file.json
# What gets executed (after decoding base64):
jq '[.entries[] < /dev/null | select(.title=="test")]|length' file.json
Working Examples vs Failing Examples
- ✅ Works:
echo '{"test": 1}' | jq '.test' - ✅ Works:
jq '.entries[0].title' file.json - ❌ Fails:
jq '[.entries[]|select(.title=="test")]' file.json - ❌ Fails:
jq '(.entries[]|select(.title=="test"))' file.json
Verified Workarounds
Workaround 1: Script File
Write("/tmp/query.sh", """#!/bin/bash
jq '[.entries[]|select(.title=="test")]|length' file.json
""")
Bash("chmod +x /tmp/query.sh && /tmp/query.sh")
# Returns correct result: 1
Workaround 2: Base64 Encoding
Write("/tmp/cmd.txt", "jq '[.entries[]|select(.title==\"test\")]|length' file.json")
Bash("encoded=$(cat /tmp/cmd.txt | base64); eval \"$(echo $encoded | base64 -d)\"")
# Returns correct result: 1
Impact
- Prevents data extraction from JSON files with array structures
- Blocks analytics and reporting workflows
- Forces developers to use complex workarounds for basic operations
- Affects any jq query using the common pattern
.array[]|filter
Test Environment
- Working directory:
~/test/
ls -l file.json
-rw-r--r-- 1 user staff 54 May 16 14:03 file.json
- Node.js based Claude Code (evident from path structure)
Minimal Reproducible Example
# Create test data
Write("file.json", '{"entries": [{"title": "test"}, {"title": "other"}]}')
# This fails:
Bash(jq '[.entries[]|select(.title=="")]|length' file.json)… Cost: $0.0275 (5.5s)
⎿ Error: jq: error: syntax error, unexpected '/' (Unix shell quoting issues?) at <top-level>, line 1:
[.entries[] < /dev/null | select(.title=="")]|length
jq: 1 compile error
# This shows the corruption:
Bash('echo \'jq "[.entries[]|select(.title==\\\"test\\\")]|length" file.json\' | base64')
# Decode reveals: < /dev/null injected into command
Scope
This bug affects a common jq pattern used in many workflows.
This issue has 11 comments on GitHub. Read the full discussion on GitHub ↗