Title: Critical Security Bug: deny permissions in settings.json are not enforced
Labels: bug, security, critical
Description
As of version 1.0.93, the deny permission system configured in settings.json files is completely non-functional. All tested deny rules are ignored, allowing Claude Code unrestricted access to files and tools that should be blocked. This presents a significant security risk for users who rely on this documented feature to protect sensitive data and prevent dangerous operations.
Based on extensive testing (see attached test results summary), the following deny rules failed to work:
- File Access:
Read, Edit, Write rules for specific files, patterns (*.env), and recursive directories (secrets/**) were all ignored.
- Tool Access: Denying entire tools like
WebFetch was ineffective.
- Command Access: Denying specific
Bash commands (e.g., rm:*) had no effect.
- Default Blocks: Even default-denied commands like
curl were executable.
The current behavior completely contradicts the official documentation, which details a robust system for restricting agent capabilities.
Steps to Reproduce
- In a project directory, create a
.claude/settings.json file with the following content:
{
"permissions": {
"deny": [
"Read(./.env)"
]
}
}
- Create a file named
.env in the same directory with some content (e.g., SECRET=123).
- Start
claude in the terminal.
- Ask Claude to:
read the .env file.
Expected Behavior:
Claude should be blocked from reading the file, stating that the permission is denied by the configuration.
Actual Behavior:
Claude successfully reads and displays the contents of the .env file, completely ignoring the deny rule.
Community Workaround: Using PreToolUse Hooks
Until the core deny functionality is fixed, the only reliable way to protect sensitive files is by using a PreToolUse hook. This solution intercepts tool calls before execution and can block them based on custom logic.
I am sharing my implementation below to help other users secure their environments and to provide the team with a clear example of the expected behavior.
1. Create the Hook Script (.claude/hooks/protect_sensitive_files.py)
This Python script checks the file_path of any Read or Edit operation against a list of sensitive patterns. If a match is found, it exits with code 2, which blocks the tool and feeds the stderr message back to Claude.
#!/usr/bin/env python3
import sys
import json
from pathlib import Path
# A list of file extensions and exact filenames considered sensitive.
SENSITIVE_PATTERNS = {
'.env', '.pem', '.key', '.credential', '.token', 'credentials.json',
'google-credentials.json', 'service-account.json', 'package-lock.json',
'poetry.lock', 'yarn.lock'
}
def main():
"""
Main function to process the hook input and check for sensitive file access.
"""
try:
# Read the JSON data passed from Claude Code via stdin
data = json.load(sys.stdin)
tool_input = data.get('tool_input', {})
file_path_str = tool_input.get('file_path')
if not file_path_str:
# If no file path is involved, the hook doesn't need to act.
sys.exit(0)
file_path = Path(file_path_str)
file_name = file_path.name
file_extension = file_path.suffix.lower()
# Check if the file name or extension matches our sensitive patterns
if file_name in SENSITIVE_PATTERNS or file_extension in SENSITIVE_PATTERNS:
# Construct a clear, educational error message for the LLM
error_message = (
f"SECURITY_POLICY_VIOLATION: Access to the sensitive file '{file_name}' is blocked by a hook.\n"
f"Reason: Files like '{file_name}' often contain credentials, private keys, or locked dependencies and should not be accessed or modified by the AI.\n"
"Action: Please use environment variables for secrets or ask for the specific information you need without reading the file directly."
)
# Print the error message to stderr
print(error_message, file=sys.stderr)
# Exit with code 2 to block the tool and feed stderr back to Claude
sys.exit(2)
except (json.JSONDecodeError, KeyError) as e:
# Handle potential errors in the input data
print(f"Error processing hook input: {e}", file=sys.stderr)
# Exit with a non-blocking error code
sys.exit(1)
# If no sensitive file was detected, exit with 0 to allow the action
sys.exit(0)
if __name__ == "__main__":
main()
(Ensure this script is executable: chmod +x .claude/hooks/protect_sensitive_files.py)
2. Configure settings.json to Use the Hook
Add the following to your .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Edit|MultiEdit|Write",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect_sensitive_files.py"
}
]
}
]
}
}
3. Test the Hook
When you ask Claude to read a blocked file (e.g., .env), it now correctly blocks the action and provides feedback:
⏺ I'll read the .env file for you.
⏺ Read(.env)
⎿ Error: Read operation blocked by hook:
- [$CLAUDE_PROJECT_DIR/.claude/hooks/protect_sensitive_files.py]: SECURITY_POLICY_VIOLATION: Access to the
sensitive file '.env' is blocked by a hook.
Reason: Files like '.env' often contain credentials, private keys, or locked dependencies and should not be
accessed or modified by the AI.
Action: Please use environment variables for secrets or ask for the specific information you need without
reading the file directly.
⏺ The hook protecting sensitive files has blocked access to the .env file. This is a security measure to
prevent exposure of credentials and private keys that are typically stored in .env files.
Request to the Claude Code Team
- Acknowledge and Investigate: Please investigate this critical bug as a high-priority security issue.
- Fix the Core Functionality: Restore the documented behavior of the
deny permission system.
- Update Documentation: In the meantime, please add a warning to the IAM documentation page to inform users that this feature is currently not functional and recommend using hooks as an alternative.
Thank you for your attention to this matter. This functionality is essential for the safe and secure use of Claude Code in both individual and enterprise environments.
Title: Critical Security Bug:
denypermissions insettings.jsonare not enforcedLabels:
bug,security,criticalDescription
As of version 1.0.93, the
denypermission system configured insettings.jsonfiles is completely non-functional. All tested deny rules are ignored, allowing Claude Code unrestricted access to files and tools that should be blocked. This presents a significant security risk for users who rely on this documented feature to protect sensitive data and prevent dangerous operations.Based on extensive testing (see attached test results summary), the following deny rules failed to work:
Read,Edit,Writerules for specific files, patterns (*.env), and recursive directories (secrets/**) were all ignored.WebFetchwas ineffective.Bashcommands (e.g.,rm:*) had no effect.curlwere executable.The current behavior completely contradicts the official documentation, which details a robust system for restricting agent capabilities.
Steps to Reproduce
.claude/settings.jsonfile with the following content:{ "permissions": { "deny": [ "Read(./.env)" ] } }.envin the same directory with some content (e.g.,SECRET=123).claudein the terminal.read the .env file.Expected Behavior:
Claude should be blocked from reading the file, stating that the permission is denied by the configuration.
Actual Behavior:
Claude successfully reads and displays the contents of the
.envfile, completely ignoring thedenyrule.Community Workaround: Using
PreToolUseHooksUntil the core
denyfunctionality is fixed, the only reliable way to protect sensitive files is by using aPreToolUsehook. This solution intercepts tool calls before execution and can block them based on custom logic.I am sharing my implementation below to help other users secure their environments and to provide the team with a clear example of the expected behavior.
1. Create the Hook Script (
.claude/hooks/protect_sensitive_files.py)This Python script checks the
file_pathof anyReadorEditoperation against a list of sensitive patterns. If a match is found, it exits with code2, which blocks the tool and feeds thestderrmessage back to Claude.(Ensure this script is executable:
chmod +x .claude/hooks/protect_sensitive_files.py)2. Configure
settings.jsonto Use the HookAdd the following to your
.claude/settings.json:{ "hooks": { "PreToolUse": [ { "matcher": "Read|Edit|MultiEdit|Write", "hooks": [ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/protect_sensitive_files.py" } ] } ] } }3. Test the Hook
When you ask Claude to read a blocked file (e.g.,
.env), it now correctly blocks the action and provides feedback:Request to the Claude Code Team
denypermission system.Thank you for your attention to this matter. This functionality is essential for the safe and secure use of Claude Code in both individual and enterprise environments.