diff --git a/LifeOS/install/hooks/Safety.hook.ts b/LifeOS/install/hooks/Safety.hook.ts index d040f57859..0061a7ecd1 100755 --- a/LifeOS/install/hooks/Safety.hook.ts +++ b/LifeOS/install/hooks/Safety.hook.ts @@ -296,7 +296,10 @@ function isAttackerWritableSource(toolName: string): boolean { // ToolSchemaLoaded hook event) is an upstream Claude Code feature request. if (toolName === "ToolSearch") return true; if (!toolName.startsWith("mcp__")) return false; - return /gmail|mail|drive|calendar|inbox/i.test(toolName); + // dropbox joins the list for the same reason drive is on it: file content + // pulled from a sync service is third-party-authored text that a stranger + // can put there (shared folders, file requests). + return /gmail|mail|drive|calendar|inbox|dropbox/i.test(toolName); } function annotate(input: { tool_name?: string; tool_response?: unknown }): void { diff --git a/LifeOS/install/hooks/hooks.json b/LifeOS/install/hooks/hooks.json index ff8b570a12..38fdc175e1 100644 --- a/LifeOS/install/hooks/hooks.json +++ b/LifeOS/install/hooks/hooks.json @@ -62,17 +62,7 @@ ] }, { - "matcher": "WebFetch", - "hooks": [ - { - "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts", - "timeout": 5 - } - ] - }, - { - "matcher": "WebSearch", + "matcher": "WebFetch|WebSearch|ToolSearch|mcp__.*([Mm]ail|[Dd]rive|[Cc]alendar|[Ii]nbox|[Dd]ropbox)", "hooks": [ { "type": "command", diff --git a/LifeOS/install/hooks/lib/safety-classifier.ts b/LifeOS/install/hooks/lib/safety-classifier.ts index 0fba1d8515..dd5028e88c 100755 --- a/LifeOS/install/hooks/lib/safety-classifier.ts +++ b/LifeOS/install/hooks/lib/safety-classifier.ts @@ -90,6 +90,13 @@ export const CREDENTIAL_PATHS: readonly RegExp[] = [ /\.aws\/credentials\b/, /\.gnupg\/(private-keys|secring)/, /(^|\s|=|@|"|')([~\$\{\}\/A-Za-z0-9._-]+\/)?\.env(\.[a-zA-Z0-9_-]+)?(\s|$|"|')/, + // procfs reaches the same secrets the entries above guard: `environ` is the + // process environment (API keys, tokens), `mem`/`maps` are its address space. + // `cat` is in SEARCH_TOOLS, so without this `cat /proc/self/environ` takes the + // read-only-command allow at classifyCommand() and prints every secret in the + // environment without a prompt. Covers literal pids, `self`, and the shell + // forms that reach the same file (`$$`, `$PID`, `${PID}`). + /\/proc\/(?:self|\d+|\$\$|\$\{?[A-Za-z_][A-Za-z0-9_]*\}?)\/(?:environ|mem|maps|cmdline)\b/, ]; export const READ_ONLY_COMMAND_PATTERNS: readonly RegExp[] = [