* Tool Guardian Hook Add Tool Guardian hook for blocking dangerous tool operations Introduces a preToolUse hook that scans Copilot agent tool invocations against ~20 threat patterns (destructive file ops, force pushes, DB drops, permission abuse, network exfiltration) and blocks or warns before execution. * Address review feedback: move hook to .github/, remove accidental log file - Move hooks/tool-guardian/ to .github/hooks/tool-guardian/ - Remove accidentally committed guard.log - Update all path references in README.md * Move log directory to .github/, revert hook files back to hooks/ - Revert hook files from .github/hooks/ back to hooks/tool-guardian/ - Update default log path to .github/logs/copilot/tool-guardian/ - Update all path references in README.md and hooks.json
name, description, tags
| name | description | tags | ||||
|---|---|---|---|---|---|---|
| Tool Guardian | Blocks dangerous tool operations (destructive file ops, force pushes, DB drops) before the Copilot coding agent executes them |
|
Tool Guardian Hook
Blocks dangerous tool operations before a GitHub Copilot coding agent executes them, acting as a safety net against destructive commands, force pushes, database drops, and other high-risk actions.
Overview
AI coding agents can autonomously execute shell commands, file operations, and database queries. Without guardrails, a misinterpreted instruction could lead to irreversible damage. This hook intercepts every tool invocation at the preToolUse event and scans it against ~20 threat patterns across 6 categories:
- Destructive file ops:
rm -rf /, deleting.envor.git - Destructive git ops:
git push --forceto main/master,git reset --hard - Database destruction:
DROP TABLE,DROP DATABASE,TRUNCATE,DELETE FROMwithoutWHERE - Permission abuse:
chmod 777, recursive world-writable permissions - Network exfiltration:
curl | bash,wget | sh, uploading files viacurl --data @ - System danger:
sudo,npm publish
Features
- Two guard modes:
block(exit non-zero to prevent execution) orwarn(log only) - Safer alternatives: Every blocked pattern includes a suggestion for a safer command
- Allowlist support: Skip specific patterns via
TOOL_GUARD_ALLOWLIST - Structured logging: JSON Lines output for integration with monitoring tools
- Fast execution: 10-second timeout; no external network calls
- Zero dependencies: Uses only standard Unix tools (
grep,sed); optionaljqfor input parsing
Installation
-
Copy the hook folder to your repository:
cp -r hooks/tool-guardian your-repo/hooks/ -
Ensure the script is executable:
chmod +x hooks/tool-guardian/guard-tool.sh -
Create the logs directory and add it to
.gitignore:mkdir -p .github/logs/copilot/tool-guardian echo ".github/logs/" >> .gitignore -
Commit the hook configuration to your repository's default branch.
Configuration
The hook is configured in hooks.json to run on the preToolUse event:
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "hooks/tool-guardian/guard-tool.sh",
"cwd": ".",
"env": {
"GUARD_MODE": "block"
},
"timeoutSec": 10
}
]
}
}
Environment Variables
| Variable | Values | Default | Description |
|---|---|---|---|
GUARD_MODE |
warn, block |
block |
warn logs threats only; block exits non-zero to prevent tool execution |
SKIP_TOOL_GUARD |
true |
unset | Disable the guardian entirely |
TOOL_GUARD_LOG_DIR |
path | .github/logs/copilot/tool-guardian |
Directory where guard logs are written |
TOOL_GUARD_ALLOWLIST |
comma-separated | unset | Patterns to skip (e.g., git push --force,npm publish) |
How It Works
- Before the Copilot coding agent executes a tool, the hook receives the tool invocation as JSON on stdin
- Extracts
toolNameandtoolInputfields (viajqif available, regex fallback otherwise) - Checks the combined text against the allowlist — if matched, skips all scanning
- Scans combined text against ~20 regex threat patterns across 6 severity categories
- Reports findings with category, severity, matched text, and a safer alternative
- Writes a structured JSON log entry for audit purposes
- In
blockmode, exits non-zero to prevent the tool from executing - In
warnmode, logs the threat and allows execution to proceed
Threat Categories
| Category | Severity | Key Patterns | Suggestion |
|---|---|---|---|
destructive_file_ops |
critical | rm -rf /, rm -rf ~, rm -rf ., delete .env/.git |
Use targeted paths or mv to back up |
destructive_git_ops |
critical/high | git push --force to main/master, git reset --hard, git clean -fd |
Use --force-with-lease, git stash, dry-run |
database_destruction |
critical/high | DROP TABLE, DROP DATABASE, TRUNCATE, DELETE FROM without WHERE |
Use migrations, backups, add WHERE clause |
permission_abuse |
high | chmod 777, chmod -R 777 |
Use 755 for dirs, 644 for files |
network_exfiltration |
critical/high | curl | bash, wget | sh, curl --data @file |
Download first, review, then execute |
system_danger |
high | sudo, npm publish |
Use least privilege; --dry-run first |
Examples
Safe command (exit 0)
echo '{"toolName":"bash","toolInput":"git status"}' | bash hooks/tool-guardian/guard-tool.sh
Blocked command (exit 1)
echo '{"toolName":"bash","toolInput":"git push --force origin main"}' | \
GUARD_MODE=block bash hooks/tool-guardian/guard-tool.sh
🛡️ Tool Guardian: 1 threat(s) detected in 'bash' invocation
CATEGORY SEVERITY MATCH SUGGESTION
-------- -------- ----- ----------
destructive_git_ops critical git push --force origin main Use 'git push --force-with-lease' or push to a feature branch
🚫 Operation blocked: resolve the threats above or adjust TOOL_GUARD_ALLOWLIST.
Set GUARD_MODE=warn to log without blocking.
Warn mode (exit 0, threat logged)
echo '{"toolName":"bash","toolInput":"rm -rf /"}' | \
GUARD_MODE=warn bash hooks/tool-guardian/guard-tool.sh
Allowlisted command (exit 0)
echo '{"toolName":"bash","toolInput":"git push --force origin main"}' | \
TOOL_GUARD_ALLOWLIST="git push --force" bash hooks/tool-guardian/guard-tool.sh
Log Format
Guard events are written to .github/logs/copilot/tool-guardian/guard.log in JSON Lines format:
{"timestamp":"2026-03-16T10:30:00Z","event":"threats_detected","mode":"block","tool":"bash","threat_count":1,"threats":[{"category":"destructive_git_ops","severity":"critical","match":"git push --force origin main","suggestion":"Use 'git push --force-with-lease' or push to a feature branch"}]}
{"timestamp":"2026-03-16T10:30:00Z","event":"guard_passed","mode":"block","tool":"bash"}
{"timestamp":"2026-03-16T10:30:00Z","event":"guard_skipped","reason":"allowlisted","tool":"bash"}
Customization
- Add custom patterns: Edit the
PATTERNSarray inguard-tool.shto add project-specific threat patterns - Adjust severity: Change severity levels for patterns that need different treatment
- Allowlist known commands: Use
TOOL_GUARD_ALLOWLISTfor commands that are safe in your context - Change log location: Set
TOOL_GUARD_LOG_DIRto route logs to your preferred directory
Disabling
To temporarily disable the guardian:
- Set
SKIP_TOOL_GUARD=truein the hook environment - Or remove the
preToolUseentry fromhooks.json
Limitations
- Pattern-based detection; does not perform semantic analysis of command intent
- May produce false positives for commands that match patterns in safe contexts (use the allowlist to suppress these)
- Scans the text representation of tool input; cannot detect obfuscated or encoded commands
- Requires tool invocations to be passed as JSON on stdin with
toolNameandtoolInputfields