anthropics / anthropics/claude-code

[BUG] /permissions silently drops existing rules with lowercase tool names when adding a new rule

Open
#92,350 0 comments 0 reactions 0 assignees View on GitHub
area:permissions bug data-loss
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist

- [ ] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) 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?

When .claude/settings.json already contains permission rules using a lowercase tool name (e.g. bash(...) instead of Bash(...)), running /permissions to add a new, correctly-cased rule causes the existing lowercase rules to be silently discarded instead of preserved or flagged as invalid.

Steps to Reproduce

Manually create .claude/settings.json with:
json
{
"permissions": {
"allow": [],
"ask": ["bash(git push *)"],
"deny": ["bash(rm -rf *)"]
}
}
Start Claude Code in that project.
Run /permissions and add a new rule, e.g. allow Bash(git commit *) under "ask".
Inspect .claude/settings.json after the change.

### What Should Happen?

The existing ask/deny rules are preserved as-is even though their casing is non-standard, or
Claude Code warns the user that bash(...) is invalid (case-sensitive, should be Bash(...)) and asks whether to fix or remove it.

### Error Messages/Logs

```shell
Actual Behavior

The existing rules disappear without warning:

json
{
"permissions": {
"allow": [],
"deny": [],
"ask": [
"Bash(git commit *)"
]
}
}
```

### Steps to Reproduce

Both the ask: bash(git push *) and deny: bash(rm -rf *) rules are gone. Only the newly added, correctly-cased rule remains.

Impact

This is a silent data-loss / security issue: a user could have a deny rule intended to block a dangerous command (e.g. rm -rf *), and adding an unrelated permission via /permissions will quietly remove that protection with no error, confirmation, or log message.

Environment

Claude Code version: (fill in claude --version)
OS: (fill in)
Settings file: .claude/settings.json (project-level, shared)

Suggested Fix

Validate tool-name casing when parsing rules, and either normalize (bash → Bash) or warn rather than dropping silently.
When /permissions rewrites the settings file, preserve any rule it doesn't recognize rather than omitting it, so unrecognized-but-present configuration isn't lost.

### Claude Model

None

### Is this a regression?

Yes, this worked in a previous version

### Last Working Version

_No response_

### Claude Code Version

2.1.261 (Claude Code)

### Platform

Other

### Operating System

macOS

### Terminal/Shell

Terminal.app (macOS)

### Additional Information

_No response_

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at the /permissions command and its handling of .claude/settings.json, then reproduce the case-sensitive lowercase bash(...) rules described in the issue. Trace how existing allow, ask, and deny entries are parsed and rewritten. Done means adding a correctly cased rule no longer silently removes existing entries, with preservation or an explicit warning for invalid casing.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authorization, cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.