feat: add InsAIts PostToolUse security monitoring hook

- Add insaits-security-monitor.py: real-time AI security monitoring
  hook that catches credential exposure, prompt injection,
  hallucinations, and 20+ other anomaly types
- Update hooks.json with InsAIts PostToolUse entry
- Update hooks/README.md with InsAIts in PostToolUse table
- Add InsAIts MCP server entry to mcp-configs/mcp-servers.json

InsAIts (https://github.com/Nomadu27/InsAIts) is an open-source
runtime security layer for multi-agent AI. It runs 100% locally
and writes tamper-evident audit logs to .insaits_audit_session.jsonl.

Install: pip install insa-its

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nomadu27
2026-03-10 01:02:58 +01:00
parent 0f416b0b9d
commit 540f738cc7
4 changed files with 217 additions and 0 deletions

View File

@@ -36,6 +36,7 @@ User request → Claude picks a tool → PreToolUse hook runs → Tool executes
| **Prettier format** | `Edit` | Auto-formats JS/TS files with Prettier after edits |
| **TypeScript check** | `Edit` | Runs `tsc --noEmit` after editing `.ts`/`.tsx` files |
| **console.log warning** | `Edit` | Warns about `console.log` statements in edited files |
| **InsAIts security monitor** | `.*` | Real-time AI security: catches credential exposure, prompt injection, hallucinations, behavioral anomalies (23 types). Writes audit log to `.insaits_audit_session.jsonl`. Requires `pip install insa-its`. [Details](../scripts/hooks/insaits-security-monitor.py) |
### Lifecycle Hooks

View File

@@ -165,6 +165,17 @@
}
],
"description": "Capture tool use results for continuous learning"
},
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "python \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/insaits-security-monitor.py\"",
"timeout": 15
}
],
"description": "InsAIts AI security monitor: catches credential exposure, prompt injection, hallucinations, and 20+ anomaly types. Requires: pip install insa-its"
}
],
"Stop": [

View File

@@ -88,6 +88,11 @@
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/your/projects"],
"description": "Filesystem operations (set your path)"
},
"insaits": {
"command": "python",
"args": ["-m", "insa_its.mcp_server"],
"description": "AI-to-AI security monitoring — anomaly detection, credential exposure, hallucination checks, forensic tracing. 23 anomaly types, OWASP MCP Top 10 coverage. 100% local. Install: pip install insa-its"
}
},
"_comments": {

View File

@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""
InsAIts Security Monitor — PostToolUse Hook for Claude Code
============================================================
Real-time security monitoring for Claude Code tool outputs.
Catches credential exposure, prompt injection, behavioral anomalies,
hallucination chains, and 20+ other anomaly types — runs 100% locally.
Writes audit events to .insaits_audit_session.jsonl for forensic tracing.
Setup:
pip install insa-its
Add to .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "python scripts/hooks/insaits-security-monitor.py"
}
]
}
]
}
}
How it works:
Claude Code passes tool result as JSON on stdin.
This script runs InsAIts anomaly detection on the output.
Exit code 0 = clean (pass through).
Exit code 2 = critical issue found (blocks action, shows feedback to Claude).
Detections include:
- Credential exposure (API keys, tokens, passwords in output)
- Prompt injection patterns
- Hallucination indicators (phantom citations, fact contradictions)
- Behavioral anomalies (context loss, semantic drift)
- Tool description divergence
- Shorthand emergence / jargon drift
All processing is local — no data leaves your machine.
Author: Cristi Bogdan — YuyAI (https://github.com/Nomadu27/InsAIts)
License: Apache 2.0
"""
import sys
import json
import os
import hashlib
import time
# Try importing InsAIts SDK
try:
from insa_its import insAItsMonitor
INSAITS_AVAILABLE = True
except ImportError:
INSAITS_AVAILABLE = False
AUDIT_FILE = ".insaits_audit_session.jsonl"
def extract_content(data):
"""Extract inspectable text from a Claude Code tool result."""
tool_name = data.get("tool_name", "")
tool_input = data.get("tool_input", {})
tool_result = data.get("tool_response", {})
text = ""
context = ""
if tool_name in ("Write", "Edit", "MultiEdit"):
text = tool_input.get("content", "") or tool_input.get("new_string", "")
context = "file:" + tool_input.get("file_path", "")[:80]
elif tool_name == "Bash":
if isinstance(tool_result, dict):
text = tool_result.get("output", "") or tool_result.get("stdout", "")
elif isinstance(tool_result, str):
text = tool_result
context = "bash:" + str(tool_input.get("command", ""))[:80]
elif "content" in data:
content = data["content"]
if isinstance(content, list):
text = "\n".join(
b.get("text", "") for b in content if b.get("type") == "text"
)
elif isinstance(content, str):
text = content
context = data.get("task", "")
return text, context
def write_audit(event):
"""Append an audit event to the JSONL audit log."""
try:
event["timestamp"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
event["hash"] = hashlib.sha256(
json.dumps(event, sort_keys=True).encode()
).hexdigest()[:16]
with open(AUDIT_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(event) + "\n")
except OSError:
pass
def format_feedback(anomalies):
"""Format detected anomalies as feedback for Claude Code."""
lines = [
"== InsAIts Security Monitor — Issues Detected ==",
"",
]
for i, a in enumerate(anomalies, 1):
sev = getattr(a, "severity", "MEDIUM")
atype = getattr(a, "type", "UNKNOWN")
detail = getattr(a, "detail", "")
lines.extend([
f"{i}. [{sev}] {atype}",
f" {detail[:120]}",
"",
])
lines.extend([
"-" * 56,
"Fix the issues above before continuing.",
"Audit log: " + AUDIT_FILE,
])
return "\n".join(lines)
def main():
raw = sys.stdin.read().strip()
if not raw:
sys.exit(0)
try:
data = json.loads(raw)
except json.JSONDecodeError:
data = {"content": raw}
text, context = extract_content(data)
# Skip very short or binary content
if len(text.strip()) < 10:
sys.exit(0)
if not INSAITS_AVAILABLE:
print(
"[InsAIts] Not installed. Run: pip install insa-its",
file=sys.stderr,
)
sys.exit(0)
# Enable dev mode (no API key needed for local detection)
os.environ.setdefault("INSAITS_DEV_MODE", "true")
monitor = insAItsMonitor(session_name="claude-code-hook")
result = monitor.send_message(
text=text[:4000],
sender_id="claude-code",
llm_id=os.environ.get("INSAITS_MODEL", "claude-opus"),
)
anomalies = result.get("anomalies", [])
# Write audit event regardless of findings
write_audit({
"tool": data.get("tool_name", "unknown"),
"context": context,
"anomaly_count": len(anomalies),
"anomaly_types": [getattr(a, "type", "") for a in anomalies],
"text_length": len(text),
})
if not anomalies:
if os.environ.get("INSAITS_VERBOSE"):
print("[InsAIts] Clean — no anomalies.", file=sys.stderr)
sys.exit(0)
# Check severity
has_critical = any(
getattr(a, "severity", "") in ("CRITICAL", "critical") for a in anomalies
)
feedback = format_feedback(anomalies)
if has_critical:
print(feedback) # stdout -> Claude Code shows to model
sys.exit(2) # block action
else:
print(feedback, file=sys.stderr) # stderr -> logged only
sys.exit(0)
if __name__ == "__main__":
main()