False Positive: Security Hook Blocking Write Tool on Non-Code Files
Status Closed — not planned
Maintainer reply None cached
Workaround ✓ Mentioned in description ↑
Activity 9 comments · opened Nov 1, 2025 · closed Jan 30, 2026
False Positive: Security Hook Blocking Write Tool on Non-Code Files
Summary
The PreToolUse:Callback security hook is incorrectly blocking the Write tool when creating markdown documentation files, triggering a command injection warning despite no shell execution occurring.
Environment
- Platform: macOS (Darwin 24.3.0)
- Model: claude-sonnet-4-5-20250929
- Claude Code: 2.0.31
Issue Description
When attempting to write a markdown file using the Write tool, a security hook is incorrectly blocking the operation with this error:
Write(00-introduction.md)
⎿ PreToolUse:Callback hook returned blocking error
⎿ Error: ⚠️ Security Warning: Using child_process.exec() can lead to command injection vulnerabilities.
This codebase provides a safer alternative: src/utils/execFileNoThrow.ts
Instead of:
exec(`command ${userInput}`)
Use:
import { execFileNoThrow } from '../utils/execFileNoThrow.js'
await execFileNoThrow('command', [userInput])
Problem
- False Positive Detection: The
Writetool does not usechild_process.exec()- it's a file system operation - Incorrect Context: The security warning references source code patterns (
src/utils/execFileNoThrow.ts) but is triggered on markdown file creation - Blocks Legitimate Operations: Prevents writing documentation and non-executable files
- Confusing Error Message: Suggests code-level fixes for a file operation that doesn't involve shell execution
Expected Behavior
The security hook should:
- Only trigger on actual shell command execution (Bash tool, exec calls, etc.)
- Allow
Writetool operations on non-executable files (.md, .txt, .json, .yaml) - Distinguish between file content and shell commands
- Not block documentation file creation
Actual Behavior
The hook incorrectly:
- Treats markdown file writes as potential command injection vectors
- Blocks the
Writetool based on filename or content patterns - Provides irrelevant remediation advice for file operations
Reproduction Steps
- Use the
Writetool to create a markdown file:
````
Write("/path/to/00-introduction.md", <markdown_content>)
- Observe the
PreToolUse:Callback hook returned blocking error - Note the command injection warning despite no shell execution
Proposed Solutions
Option 1: Scope Hook to Bash Tool Only
// Only apply command injection checks to Bash tool
if (tool.name === 'Bash' && containsUnsafePattern(tool.command)) {
return blockingError;
}
Option 2: Whitelist Safe File Extensions
// Allow Write operations on documentation files
const safeExtensions = ['.md', '.txt', '.json', '.yaml', '.yml', '.toml'];
if (tool.name === 'Write' && isSafeExtension(tool.file_path)) {
return allowOperation;
}
Option 3: Content-Based Analysis
// Only check for command injection in shell contexts
if (tool.name === 'Bash' || isShellExecution(tool)) {
return analyzeCommandInjection(tool);
}
Impact
- Severity: Medium-High
- Affected Users: Anyone using Claude Code to create documentation or configuration files
- Workaround: None available - hook blocks the operation entirely
- Frequency: Occurs on every
Writetool invocation for certain file patterns
Additional Context
This appears to be a hook configuration issue where:
- The pattern matching is too broad (possibly regex matching on content vs. context)
- The hook doesn't differentiate between tool types (Write vs. Bash)
- Security checks intended for shell execution are applied to file I/O
Related Issues
- This may affect other file operation tools (Edit, NotebookEdit)
- Could block legitimate workflows involving file generation
- May impact automated documentation generation
Requested Fix
Please update the security hook to:
- Only apply command injection checks to shell execution contexts (Bash tool)
- Exclude file operation tools (Write, Edit) from shell security checks
- Add tool-specific validation logic
- Improve error messages to indicate which tool/operation triggered the block
9 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
gets triggered with the word exec
exec is triggering that, even when writing to md file. It would also get triggered on writing simple things like: $response = curl_exec($ch);
And why would we want hardcoded assumptions about typescript, leading to the suggestion injected about using
execFileNoThrow.ts?This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
still occurring
This issue has been automatically closed due to 60 days of inactivity. If you're still experiencing this issue, please open a new issue with updated information.
This issue was closed incorrectly despite recent human comments. This behavior of the bot is reported at https://github.com/anthropics/claude-code/issues/16497. Please upvote that issue, so maybe it gets noticed.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.