feat(safety): PreToolUse hook gating destructive tool calls (FNDG-04b) #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "security/fndg-04b-dangerously-skip-permissions"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
FNDG-04b Option A (decided by Olivier 2026-04-19): deploy a
PreToolUsehook into every project before launching a Claude Code agent. The hook blocks destructive Bash/Edit/Write patterns so--dangerously-skip-permissionscannot be leveraged via MCPsessions.sendinto arbitrary execution.internal/safety/package —go:embedhook script +EnsureHookDeployed(projectDir)that writes the hook (0555) and merges.claude/settings.jsonwithout touching other keys.internal/dispatcher/dispatcher.golaunchAgent(fail-closed) andinternal/switcher/account_switcher.gorelaunchDedicatedSessions(fail-open — initial deploy remains in place).rm -rfon root/home,dd of=/dev/*,mkfs*,git push --force(allows--force-with-lease),git reset --hardon main/master/production,sudooutside allowlist,curl|sh, fork bomb,chmod 777on system paths, writes to.claude/settings*.json,.claude/hooks/,~/.ssh/authorized_keys, shell rc,/etc/sudoers*,/etc/systemd/*.kubectl delete,helm uninstall,terraform destroy, destructive SQL.Scope note: This is Option A only. Option C (two separate pools
ccl-auto-*+ccl-safe-*) will be handled in a separate task.Cross-repo coordination: FNDG-04 input sanitization in
secuaas-mcpis the first line of defence; this PR is the second line. The bash dispatcherlib-common.sh(indev-management/agent-orchestrator/) also needs to source this hook — that wiring is tracked as a follow-up task.Test plan
go build ./...cleango vet ./...cleango test ./internal/safety/...— 8 tests pass (file layout, idempotence, merge preserving existingsecurity-gate.sh, matcher refresh, empty-dir rejection, 9 destructive inputs blocked, 7 benign inputs allowed)go test ./internal/dispatcher/...— newTestDispatchProjectDeploysSafetyHookverifies the hook is written before anyclaudeinvocationgo test ./...full suite passrm -rf ~viasessions.send, verify blocked + logged in~/.claude/safety-hook.log(to be done post-merge on staging)docs/audit-mcp-stdio-2026-04-18.mdto mark FNDG-04b as "CORRIGÉ partiellement (Option A) commit$(git rev-parse HEAD)— Option C en cours" (follow-up commit in secuaas-mcp)References
.agent-queue/inbox/20260418-211102-fndg-04b-dangerously-skip-permissions-sessions-headless.mdsecuaas-mcpbranchaudit/mcp-stdio-2026-04-18docs/security/claude-safety-hook.md🤖 Generated with Claude Code
Adds internal/safety/ — the in-repo source of truth for the PreToolUse hook deployed into every project before a Claude Code agent is launched. The hook blocks destructive Bash/Edit/Write patterns on sessions running with --dangerously-skip-permissions, closing the exploitation path where a prompt injection via MCP sessions.send could otherwise trigger arbitrary destruction without interactive confirmation. Wire-up: - internal/dispatcher/dispatcher.go launchAgent: deploys hook before claude launch; fail-closed if deployment fails. - internal/switcher/account_switcher.go relaunchDedicatedSessions: redeploys hook before --resume after account failover; fail-open (log + continue) since the initial deployment is still in place. Blocks (exit 2, stderr shown to model): - rm -rf targeting /, ~, $HOME, /etc, /var, /usr, /boot - dd of=/dev/{sd,nvme,disk,hd,mmcblk}*, mkfs* - git push --force (but allows --force-with-lease) - git reset --hard on main|master|production - sudo outside short allowlist (systemctl, journalctl, cp, install, apt*) - curl|sh, bash <(curl ...), eval "$(curl ...)", fork bomb, crontab -e - chmod 777 on system paths / home - Writes to .claude/settings*.json, .claude/hooks/, ~/.ssh/authorized_keys, shell rc files, /etc/sudoers*, /etc/systemd/* Warn-only (logged, not blocked): - kubectl delete, helm uninstall, terraform destroy - DROP TABLE, TRUNCATE TABLE, DELETE FROM ... WHERE 1=1 Hook script is embedded via //go:embed so a single binary release carries the authoritative copy. Every launch rewrites the deployed file with mode 0555 (anti-tamper); the hook itself also blocks writes to .claude/hooks/ for defense in depth. Decision: Olivier, 2026-04-19 — Option A now, Option C (two pools) tracked separately. Complements FNDG-04 input sanitization in secuaas-mcp. Tests: 8 unit/integration tests in internal/safety/, plus a dispatcher-level test verifying the hook is written before launch. go vet clean, go test ./... all pass. Refs: FNDG-04 audit (secuaas-mcp branch audit/mcp-stdio-2026-04-18) Task: .agent-queue/inbox/20260418-211102-fndg-04b-*.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.