Plugin PreToolUse hooks silently override `bypassPermissions` / `acceptEdits` with no indication to the user
Summary
A plugin can register a PreToolUse hook that forces a confirmation prompt on every matching tool call, and this overrides the user's permission mode (acceptEdits, bypassPermissions) and the user's allowlist entries. The user has no in-session indication that the prompt is coming from a plugin hook rather than from the normal permission system, and no way to tell from the prompt UI which plugin is responsible.
Concrete case
The official plugin security-guidance@claude-plugins-official (file: ~/.claude/plugins/cache/claude-plugins-official/security-guidance/unknown/hooks/hooks.json) registers:
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{ "type": "command", "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py" }
],
"matcher": "Edit|Write|MultiEdit"
}
]
}
}
With this plugin enabled, every single Edit, Write, and MultiEdit call triggers a confirmation prompt — even when the user has all of:
permissions.defaultMode: "acceptEdits"permissions.allowcontainingBash(*),Read,Write,Edit,MultiEdit,NotebookEdit- Toggled
auto-accept edits(shift+tab) on at the session level
The prompt UI shows only the standard "Do you want to make this edit? [Yes / Yes, allow all edits during this session / No]" — there is nothing identifying that a plugin hook is the source, and clicking "Yes, allow all edits during this session" does not stick because the hook re-fires on the next tool call.
User-visible impact
I spent ~6–7 sessions trying to figure out why acceptEdits had stopped working. I rewrote my settings, added wildcard allowlist entries, switched to bypassPermissions, restarted Claude Code repeatedly — none of it helped, because the prompt was coming from the plugin hook layer, not the permission layer. The cause was only found by greping the plugin cache for hooks.json files.
Suggested fixes
Any of these would be enough on their own:
- Surface plugin-originated prompts visually, e.g. label them "from
security-guidanceplugin" so users know which knob to turn. - Make plugin hooks honor
bypassPermissions(or document loudly that they don't, and provide a way to disable plugin hooks for a session — a flag, an/unhookcommand, etc.). - Make plugin enable/disable state more visible — the user usually doesn't remember which plugins are active or what hooks they registered.
- At minimum, document this behavior clearly in the plugin docs and the
permissionsdocs.
Environment
- Claude Code 2.1.123
- macOS Darwin 25.5.0
- Plugin:
security-guidance@claude-plugins-official, versionunknownper the cache directory name
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗