Permission system saves entire heredoc contents as Bash permission entry
Bug Description
When a Claude Code session uses Bash with heredoc/cat << EOF syntax to write files, and the user clicks "Allow" or "Don't ask again" on the permission prompt, the entire command including all file contents is saved verbatim as a single permission entry in .claude/settings.local.json.
This corrupts the settings file with multi-kilobyte entries that are not functional permissions.
Reproduction Steps
- Have Claude Code write a file using Bash heredoc:
``bash``
cat > /path/to/file.md << 'EOF'
# Large markdown file contents
... (thousands of characters)
EOF
- When the permission prompt appears, click "Allow" or "Don't ask again"
- Check
.claude/settings.local.json
Expected Behavior
Either:
- The permission should be normalized/truncated to a pattern like
Bash(cat > /path/to/file.md:*) - Or heredoc commands should not be saved as permission entries at all (since the Write tool should be used instead)
Actual Behavior
The full command including all file contents is saved as a single permission entry:
"Bash(/path/to/file.md << 'EOF'\n# Full file contents here\n... (3000+ characters) ...\nEOF)"
This causes:
settings.local.jsonto balloon from ~2KB to 50KB+- Invalid/non-functional permission entries
- The file becomes unreadable and must be manually cleaned
- Recurring corruption if the pattern keeps happening across sessions
Environment
- Claude Code (CLI)
- macOS (Darwin 25.2.0)
- Multiple concurrent Claude Code sessions on same project accelerate the issue
- Both project-level
.claude/settings.local.jsonand global~/.claude/settings.local.jsonaffected
Observed Corrupted Entries (examples)
Entries like these appeared in settings.local.json:
"Bash(/path/to/research/map-ux-study/WORKFLOW.md << 'EOF'\n# Map UX Research Workflow\n\n```\n┌────────...3000+ chars...EOF)"
"Bash(/path/to/research/map-ux-study/FINDINGS-TEMPLATE.md << 'EOF'\n# Map UX Research Findings\n...5000+ chars...EOF)"
"Bash(Skip\" for September. Reduced max crowd penalty to 30%...commit message contents...EOF\n\\)\")"
Also saw shell loop fragments saved as individual permissions:
"Bash(for dir in */)"
"Bash(do)"
"Bash(then)"
"Bash(fi)"
"Bash(done)"
Suggested Fix
When saving a Bash permission entry, either:
- Truncate the command at a reasonable length (e.g., 200 chars) and replace the rest with
* - Reject heredoc patterns entirely from being saved as permissions
- Normalize the permission to just the command prefix before the heredoc marker
🤖 Generated with Claude Code
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗