fix: make insaits hook opt-in

This commit is contained in:
Affaan Mustafa
2026-03-10 20:47:09 -07:00
parent 9ea415c037
commit 9c1e8dd1e4
5 changed files with 56 additions and 5 deletions

View File

@@ -25,7 +25,7 @@ User request → Claude picks a tool → PreToolUse hook runs → Tool executes
| **Git push reminder** | `Bash` | Reminds to review changes before `git push` | 0 (warns) |
| **Doc file warning** | `Write` | Warns about non-standard `.md`/`.txt` files (allows README, CLAUDE, CONTRIBUTING, CHANGELOG, LICENSE, SKILL, docs/, skills/); cross-platform path handling | 0 (warns) |
| **Strategic compact** | `Edit\|Write` | Suggests manual `/compact` at logical intervals (every ~50 tool calls) | 0 (warns) |
| **InsAIts security monitor** | `*` | Detects credential exposure, prompt injection, hallucinations, and behavioral anomalies (23 types) before tool execution. Blocks on critical findings, warns on non-critical. Writes audit log to `.insaits_audit_session.jsonl`. Requires `pip install insa-its`. [Details](../scripts/hooks/insaits-security-monitor.py) | 2 (blocks critical) / 0 (warns) |
| **InsAIts security monitor (opt-in)** | `Bash\|Write\|Edit\|MultiEdit` | Optional security scan for high-signal tool inputs. Disabled unless `ECC_ENABLE_INSAITS=1`. Blocks on critical findings, warns on non-critical, and writes audit log to `.insaits_audit_session.jsonl`. Requires `pip install insa-its`. [Details](../scripts/hooks/insaits-security-monitor.py) | 2 (blocks critical) / 0 (warns) |
### PostToolUse Hooks

View File

@@ -65,7 +65,7 @@
"description": "Capture tool use observations for continuous learning"
},
{
"matcher": "*",
"matcher": "Bash|Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
@@ -73,7 +73,7 @@
"timeout": 15
}
],
"description": "InsAIts AI security monitor: detects credential exposure, prompt injection, hallucinations, and 20+ anomaly types before tool execution. Requires: pip install insa-its"
"description": "Optional InsAIts AI security monitor for Bash/Edit/Write flows. Enable with ECC_ENABLE_INSAITS=1. Requires: pip install insa-its"
}
],
"PreCompact": [

View File

@@ -11,17 +11,18 @@ Writes audit events to .insaits_audit_session.jsonl for forensic tracing.
Setup:
pip install insa-its
export ECC_ENABLE_INSAITS=1
Add to .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": ".*",
"matcher": "Bash|Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "python3 scripts/hooks/insaits-security-monitor.py"
"command": "node scripts/hooks/insaits-security-wrapper.js"
}
]
}

View File

@@ -16,6 +16,10 @@ const { spawnSync } = require('child_process');
const MAX_STDIN = 1024 * 1024;
function isEnabled(value) {
return ['1', 'true', 'yes', 'on'].includes(String(value || '').toLowerCase());
}
let raw = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', chunk => {
@@ -25,6 +29,11 @@ process.stdin.on('data', chunk => {
});
process.stdin.on('end', () => {
if (!isEnabled(process.env.ECC_ENABLE_INSAITS)) {
process.stdout.write(raw);
process.exit(0);
}
const scriptDir = __dirname;
const pyScript = path.join(scriptDir, 'insaits-security-monitor.py');

View File

@@ -203,6 +203,24 @@ async function runTests() {
}
})) passed++; else failed++;
// insaits-security-wrapper.js tests
console.log('\ninsaits-security-wrapper.js:');
if (await asyncTest('passes through input unchanged when integration is disabled', async () => {
const stdinData = JSON.stringify({
tool_name: 'Write',
tool_input: { file_path: 'src/index.ts', content: 'console.log("ok");' }
});
const result = await runScript(
path.join(scriptsDir, 'insaits-security-wrapper.js'),
stdinData,
{ ECC_ENABLE_INSAITS: '' }
);
assert.strictEqual(result.code, 0, `Exit code should be 0, got ${result.code}`);
assert.strictEqual(result.stdout, stdinData, 'Should pass stdin through unchanged');
assert.strictEqual(result.stderr, '', 'Should stay silent when integration is disabled');
})) passed++; else failed++;
// check-console-log.js tests
console.log('\ncheck-console-log.js:');
@@ -1237,6 +1255,29 @@ async function runTests() {
}
})) passed++; else failed++;
if (test('InsAIts hook is opt-in and scoped to high-signal tool inputs', () => {
const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');
const hooks = JSON.parse(fs.readFileSync(hooksPath, 'utf8'));
const insaitsHook = hooks.hooks.PreToolUse.find(entry =>
entry.description && entry.description.includes('InsAIts')
);
assert.ok(insaitsHook, 'Should define an InsAIts PreToolUse hook');
assert.strictEqual(
insaitsHook.matcher,
'Bash|Write|Edit|MultiEdit',
'InsAIts hook should avoid matching every tool'
);
assert.ok(
insaitsHook.description.includes('ECC_ENABLE_INSAITS=1'),
'InsAIts hook should document explicit opt-in'
);
assert.ok(
insaitsHook.hooks[0].command.includes('insaits-security-wrapper.js'),
'InsAIts hook should execute through the JS wrapper'
);
})) passed++; else failed++;
// plugin.json validation
console.log('\nplugin.json Validation:');