HookStack
Back to catalogue
SecurityPreToolUse· Write|Edit

Sensitive file write protection

Your .env and keys stay untouched by the agent

Prevents the agent from modifying sensitive files (.env, secrets, private keys, CI lockfiles) by intercepting the Write and Edit tools and checking the target path.

What does the Sensitive file write protection hook do?

Sensitive file write protection is a Claude Code PreToolUse hook matching Write|Edit. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Your .env and keys stay untouched by the agent.

As a PreToolUse hook it runs before the action completes, so it can block or adjust what Claude is about to do. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.

Use cases

  • Configuration protection
  • Compliance
  • Local secrets integrity

Tags

#security#files#protection#secrets

settings.json fragment

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/protect-paths.mjs",
            "type": "command"
          }
        ],
        "matcher": "Write|Edit"
      }
    ]
  }
}

Script · .claude/hooks/protect-paths.mjs

#!/usr/bin/env node
// @hookstack pre-edit-protect-paths
// Protège les fichiers sensibles contre l'écriture (PreToolUse Write|Edit)
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";

const PROTECTED = [
	/\/\.env$/,
	/\/\.env\.local$/,
	/\/\.env\.production/,
	/\/secrets\//,
	/\/(id_rsa|id_ed25519|.*\.pem)$/,
];

export function run(input) {
	const filePath = input.tool_input?.file_path ?? "";
	const blocked = PROTECTED.find((p) => p.test(filePath));
	return blocked
		? {
				decision: "block",
				reason: `Fichier protégé : ${filePath}. Modifiez manuellement si intentionnel.`,
			}
		: null;
}

/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
	const input = JSON.parse(readFileSync(0, "utf8"));
	const result = run(input);
	if (result) process.stdout.write(JSON.stringify(result));
}

Learn more

Related hooks