security-guidance SessionStart hook fails on Windows when CLAUDE_PLUGIN_ROOT is a backslash path
## Summary
On Windows, security-guidance@claude-plugins-official 2.0.6 can fail its SessionStart hook when CLAUDE_PLUGIN_ROOT is provided as a raw Windows backslash path. The hook command passes that value inside a double-quoted bash argument, and the backslashes are consumed before the script path is opened.
This appears to be the same class as closed/locked #21878, but the local failure is current on Claude Code 2.1.177 and #21878 asks affected users to open a new issue if still relevant.
Environment
- OS: Windows
- Claude Code CLI:
2.1.177 (Claude Code) - Plugin:
security-guidance@claude-plugins-official2.0.6 - Provider setup: not relevant to the hook-path failure
Observed behavior
A SessionStart non-blocking hook error reported a path of this shape:
/bin/bash: C:Users<user>.claudepluginscache...security-guidance2.0.6/hooks/sg-python.sh: No such file or directory
The important part is that the Windows path separators are gone: C:\Users\<user>\... became C:Users<user>.... The target file exists locally at:
~/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/sg-python.sh
~/.claude/security/log.txt could not be attached from this host because the path returns Access is denied.
Current manifest command
Local hooks/hooks.json for 2.0.6 contains:
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/sg-python.sh\" \"${CLAUDE_PLUGIN_ROOT}/hooks/ensure_agent_sdk.py\""
The same raw-root pattern is also used for UserPromptSubmit, PostToolUse, and Stop commands in this manifest.
Root cause hypothesis
When CLAUDE_PLUGIN_ROOT is a Windows backslash path, the command hands that path to bash inside a double-quoted argument. Bash consumes backslashes as escapes (\U, \t, \p, etc.), producing a mangled script path before sg-python.sh can run. The script itself cannot repair this because the failure occurs before the script is opened.
Suggested durable fix
Make the hook path bash-safe before passing it as a bash argument. For example:
- convert the root to forward slashes before composing the command, e.g.
${CLAUDE_PLUGIN_ROOT//\\//} - or
cygpath/equivalent conversion before passing the script path to bash - or have the host provide
CLAUDE_PLUGIN_ROOTin a bash-safe form when invoking bash hooks on Windows
Local interim mitigation is disabling security-guidance@claude-plugins-official in user settings, but that loses the plugin's supplemental security warnings until the upstream/host fix lands.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗