HookStack
Back to catalogue
SecurityPreToolUse· Bash

Sudo usage warning

Flags privilege escalation before it hangs your loop

Non-blocking advisory whenever a Bash command reaches for sudo. Privilege escalation is rarely needed in a dev loop and a non-interactive password prompt can silently stall the agent — this surfaces it so a venv/--user/container path is considered first.

What does the Sudo usage warning hook do?

Sudo usage warning is a Claude Code PreToolUse hook matching Bash. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Flags privilege escalation before it hangs your loop.

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

  • Least-privilege dev
  • Avoid blocked sessions
  • Awareness

Tags

#security#bash#sudo#privileges#advisory

settings.json fragment

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/warn-sudo.mjs",
            "type": "command"
          }
        ],
        "matcher": "Bash"
      }
    ]
  }
}

Script · .claude/hooks/warn-sudo.mjs

#!/usr/bin/env node
// @hookstack pre-bash-warn-sudo
// Avertit (sans bloquer) quand une commande Bash utilise sudo (PreToolUse Bash)
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";

function stripQuotedArgs(cmd) {
	return cmd
		.replace(/"(?:[^"\\]|\\.)*"/g, '""')
		.replace(/'(?:[^'\\]|\\.)*'/g, "''");
}

export function run(input) {
	if (input.tool_name && input.tool_name !== "Bash") return null;
	const command = stripQuotedArgs(input.tool_input?.command ?? "");
	// sudo en début de commande ou après un opérateur shell (; && || |).
	if (!/(?:^|[;&|]|&&|\|\|)\s*sudo\s+/.test(command)) return null;
	return {
		message:
			"[warn-sudo] Cette commande utilise sudo. Une élévation de privilèges est rarement nécessaire " +
			"dans une boucle de dev et peut bloquer sur une invite de mot de passe non interactive. " +
			"Vérifiez si une version sans sudo (venv, --user, conteneur) suffit.\n",
	};
}

/* 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?.message) process.stderr.write(result.message);
}

Learn more

Related hooks