diff --git a/hooks/hooks.json b/hooks/hooks.json index 3edc6778..64b2fe83 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -70,7 +70,6 @@ { "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/run-with-flags.js\" \"pre:insaits-security\" \"scripts/hooks/insaits-security-wrapper.js\" \"standard,strict\"", - "async": true, "timeout": 15 } ], diff --git a/scripts/hooks/insaits-security-monitor.py b/scripts/hooks/insaits-security-monitor.py index e0a8ab14..5e8c0b34 100644 --- a/scripts/hooks/insaits-security-monitor.py +++ b/scripts/hooks/insaits-security-monitor.py @@ -58,7 +58,7 @@ import logging import os import sys import time -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Tuple # Configure logging to stderr so it does not interfere with stdout protocol logging.basicConfig( @@ -87,7 +87,6 @@ def extract_content(data: Dict[str, Any]) -> Tuple[str, str]: """ tool_name: str = data.get("tool_name", "") tool_input: Dict[str, Any] = data.get("tool_input", {}) - tool_result: Any = data.get("tool_response", {}) text: str = "" context: str = "" @@ -96,16 +95,9 @@ def extract_content(data: Dict[str, Any]) -> Tuple[str, str]: text = tool_input.get("content", "") or tool_input.get("new_string", "") context = "file:" + str(tool_input.get("file_path", ""))[:80] elif tool_name == "Bash": + # PreToolUse: the tool hasn't executed yet, inspect the command command: str = str(tool_input.get("command", "")) - # For PreToolUse we inspect the command itself text = command - # Also check tool_response if present (for flexibility) - if isinstance(tool_result, dict): - output = tool_result.get("output", "") or tool_result.get("stdout", "") - if output: - text = text + "\n" + output - elif isinstance(tool_result, str) and tool_result: - text = text + "\n" + tool_result context = "bash:" + command[:80] elif "content" in data: content: Any = data["content"] diff --git a/scripts/hooks/insaits-security-wrapper.js b/scripts/hooks/insaits-security-wrapper.js index 6223b368..eba87128 100644 --- a/scripts/hooks/insaits-security-wrapper.js +++ b/scripts/hooks/insaits-security-wrapper.js @@ -54,9 +54,24 @@ process.stdin.on('end', () => { process.exit(0); } + // Log non-ENOENT spawn errors (timeout, signal kill, etc.) so users + // know the security monitor did not run — fail-open with a warning. + if (result.error) { + process.stderr.write(`[InsAIts] Security monitor failed to run: ${result.error.message}\n`); + process.stdout.write(raw); + process.exit(0); + } + if (result.stdout) process.stdout.write(result.stdout); if (result.stderr) process.stderr.write(result.stderr); - const code = Number.isInteger(result.status) ? result.status : 0; - process.exit(code); + // result.status is null when the process was killed by a signal or + // timed out. Treat that as an error rather than silently passing. + if (!Number.isInteger(result.status)) { + const signal = result.signal || 'unknown'; + process.stderr.write(`[InsAIts] Security monitor killed (signal: ${signal}). Tool execution continues.\n`); + process.exit(0); + } + + process.exit(result.status); });