Security: disableAllHooks bypasses managed organization hooks
Bug Report: disableAllHooks Bypasses Managed Organization Hooks
Summary
disableAllHooks: true in project-level local settings (.claude/settings.local.json) can bypass managed/organization-level hooks defined in /Library/Application Support/ClaudeCode/managed-settings.json, contradicting documentation and breaking the security model.
Security Impact
HIGH - Organizations relying on managed hooks for security policies (e.g., preventing dangerous commands, enforcing code scanning, blocking secrets) can be bypassed by any user with a single line in their local settings.
Steps to Reproduce
1. Create Managed Hook (Organization Level)
Create /Library/Application Support/ClaudeCode/managed-settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "echo ':no_entry_sign: MANAGED HOOK BLOCKING - This is from managed-settings.json' && exit 2",
"timeout": 5000
}
]
}
]
}
}
2. Restart Claude Code
Hooks are loaded at session startup, so restart is required.
3. Test Without Bypass
Send any message - it should be blocked by the managed hook.
4. Add Bypass in Local Settings
Add to .claude/settings.local.json in your project:
{
"disableAllHooks": true
}
5. Restart Claude Code Again
6. Test With Bypass
Send any message - managed hook is bypassed, message goes through.
Expected Behavior (Per Documentation)
According to the official documentation and the claude-code-guide agent:
Managed settings take absolute precedence: When an organization administrator sets hooks through server-managed or endpoint-managed settings, these hooks operate at the highest tier and cannot be overridden by any user-level configuration.
Settings precedence hierarchy (from docs):
1. Managed Settings (highest - cannot be overridden) ← Should prevent bypass
↓
2. Command Line Arguments
↓
3. Local Project Settings (.claude/settings.local.json) ← disableAllHooks here
↓
4. Project Settings
↓
5. User Settings (lowest)
The documentation explicitly states that disableAllHooks should NOT affect managed hooks:
While you can set "disableAllHooks": true in your local settings, this will only disable hooks defined at lower precedence levels (project and user settings). It has no effect on managed hooks.
Actual Behavior
disableAllHooks: true in local settings DOES bypass managed hooks, completely contradicting the documented behavior and security model.
Environment
- Claude Code Version: [Current version]
- OS: macOS (Darwin 24.6.0)
- Managed settings location:
/Library/Application Support/ClaudeCode/managed-settings.json - Local settings location:
.claude/settings.local.json
Security Recommendations
- Immediate Fix Needed:
disableAllHooksshould NEVER disable managed hooks regardless of where it's set - Document Correctly: If this is intended behavior, documentation needs urgent correction and organizations should be warned
- Consider Alternative: Add separate
disableAllHooksExceptManaged: trueoption, or make managed hooks immune to all disable flags - Audit Trail: Consider logging when
disableAllHooksis used to help detect policy bypass attempts
References
- Settings Precedence: https://code.claude.com/docs/en/settings.md#settings-precedence
- Server-Managed Settings: https://code.claude.com/docs/en/server-managed-settings.md
- Hooks Configuration: https://code.claude.com/docs/en/hooks.md#hook-locations
Tested By
Date: 2026-02-18
Tester: Nir Ayalon
Verified: Managed hook successfully bypassed using local settings
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗