[BUG] No write-time validation for permission patterns causes settings corruption

Resolved 💬 6 comments Opened Dec 22, 2025 by einfachWitzlos Closed Feb 25, 2026

What's Wrong?

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

Bug Description

When Claude Code prompts for permission on Bash commands containing environment variables (e.g., SSH_AUTH_SOCK=...), clicking "Always allow" saves invalid patterns to the settings file.

The saved patterns use incorrect syntax that Claude Code itself rejects on the next startup, causing the entire settings file to be skipped.

The Core Problem

Write path has no validation, but read path does.

  1. Claude runs a command like: SSH_AUTH_SOCK=/tmp/ssh-XXXXXX/agent.1234 ssh-add -l
  2. User clicks "Always allow"
  3. Claude Code saves: "Bash(SSH_AUTH_SOCK=*)"Invalid syntax
  4. On next startup: ⚠ Found invalid settings files. They will be ignored.
  5. /doctor shows:

``
Invalid Settings .claude/settings.local.json
└ permissions
└ allow
└ "Bash(SSH_AUTH_SOCK=*)": Use ":*" for prefix matching, not just "*".
Change to "Bash(SSH_AUTH_SOCK=:*)" for prefix matching.
``

Why This Is Critical

  • Silent data loss: All other valid settings in the file are also ignored (in my case 70+ carefully configured allow rules)
  • Recurring issue: User keeps hitting "Always allow" → keeps corrupting the file
  • No warning at write time: User has no idea the pattern is invalid until next session
  • Requires manual intervention: Must hand-edit JSON to fix
  • Overly specific patterns: "Always allow" also saves useless session-specific patterns like full temp paths

Real-World Examples from My Settings

These patterns were automatically generated by clicking "Always allow":

Invalid Patterns (cause settings to be skipped entirely)

"Bash(SSH_AUTH_SOCK=*)"

Error: Use ":*" for prefix matching, not just "*". Change to "Bash(SSH_AUTH_SOCK=:*)"

Useless Over-Specific Patterns (saved but will never match again)

"Bash(SSH_AUTH_SOCK=/tmp/ssh-XXXXXXf0Vl4w/agent.9840 ssh-add:*)"
"Bash(SSH_AUTH_SOCK=/tmp/ssh-JqzBQXKuG1AX/agent.9840 ssh-add:*)"
"Bash(SSH_AUTH_SOCK=/tmp/ssh-JqzBQXKuG1AX/agent.9840 ssh:*)"
"Bash(SSH_AUTH_SOCK=$SSH_AUTH_SOCK ssh:*)"

These contain session-specific temp paths that change every time. They will never match future commands.

Giant Commit Message Patterns (absurd)

"Always allow" even saved entire git commit messages as patterns:

"Bash(git commit -m \"$(cat <<'EOF'\nAdd comprehensive caching layer...\n[500+ characters of commit message]\nEOF\n)\")"

This is clearly not a reusable pattern.

Related Issues

  • #8581 - Permission wildcards not working for env vars (closed as duplicate)
  • #5886 - Settings validation passes invalid types (open, related validation issue)
  • #2593 - Config corruption from concurrent sessions (different root cause)
  • #11172 - "Always allow" not persisting (possibly related)

Workaround

I've written a bash script that fixes these patterns before starting Claude Code. Happy to share if others need it.

What Should Happen?

What Should Happen

For Invalid Syntax

Option A (Preferred): Validate patterns before saving. If the pattern would be invalid:

  • Auto-correct it (*:* for env var prefixes)
  • Or show an error and don't save
  • Or ask the user to confirm a corrected version

Option B: Make the read-path more tolerant:

  • Warn about invalid patterns but don't skip the entire file
  • Ignore only the invalid entries, keep the rest

For Over-Specific Patterns

When a command contains:

  • Temp paths (/tmp/ssh-XXXXX/...)
  • Variable expansions ($SSH_AUTH_SOCK)
  • Multi-line content (heredocs, commit messages)

Claude Code should either:

  • Generalize the pattern (e.g., SSH_AUTH_SOCK=/tmp/... ssh-addBash(SSH_AUTH_SOCK=:*))
  • Warn the user that this pattern is too specific to be useful
  • Not save it at all and suggest adding a general pattern manually

Error Messages/Logs

Example patterns saved by "Always allow" that cause settings corruption:

INVALID PATTERNS (cause entire settings file to be skipped):
  "Bash(SSH_AUTH_SOCK=*)"

USELESS PATTERNS (session-specific, will never match again):
  "Bash(SSH_AUTH_SOCK=/tmp/ssh-XXXXXX/agent.1234 ssh-add:*)"
  "Bash(SSH_AUTH_SOCK=/tmp/ssh-YYYYYY/agent.5678 ssh-add:*)"
  "Bash(SSH_AUTH_SOCK=$SSH_AUTH_SOCK ssh:*)"

ABSURD PATTERNS (entire commit messages saved as "patterns"):
  "Bash(git commit -m \"$(cat <<'EOF'\n[500+ character commit message]\nEOF\n)\")"

---

/doctor output on next startup:

Invalid Settings .claude/settings.local.json
└ permissions
  └ allow
    └ "Bash(SSH_AUTH_SOCK=*)": Use ":*" for prefix matching, not just "*".
      Change to "Bash(SSH_AUTH_SOCK=:*)" for prefix matching.

---

Startup warning:

⚠ Found invalid settings files. They will be ignored. Run /doctor for details.

---

Result: All 70+ valid permission entries in the file are also ignored.

Steps to Reproduce

Steps to Reproduce

  1. Start Claude Code in any project
  2. Ensure SSH agent is running with a socket (common on Linux/WSL)
  3. Ask Claude to run: ssh-add -l or any SSH command
  4. Claude will prepend SSH_AUTH_SOCK=... to the command
  5. When prompted, click "Always allow"
  6. Exit Claude Code
  7. Restart Claude Code
  8. Observe: ⚠ Found invalid settings files. They will be ignored.
  9. All your other permissions are now also ignored

Environment

  • Claude Code Version: Latest (issue persists across versions)
  • Platform: Linux (WSL2 Ubuntu 24.04)
  • Terminal: zsh
  • Shell: zsh with ssh-agent running

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.0.75 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

_No response_

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗