-
-
Notifications
You must be signed in to change notification settings - Fork 74
Expand file tree
/
Copy pathclaude-code.ts
More file actions
88 lines (74 loc) · 2.14 KB
/
Copy pathclaude-code.ts
File metadata and controls
88 lines (74 loc) · 2.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { analyzeCommand, loadConfig } from '@/core/analyze';
import { redactSecrets, writeAuditLog } from '@/core/audit';
import { envTruthy } from '@/core/env';
import { formatBlockedMessage } from '@/core/format';
import type { HookInput, HookOutput } from '@/types';
function outputDecision(
decision: 'deny' | 'ask',
reason: string,
command?: string,
segment?: string,
): void {
const message = formatBlockedMessage({
reason,
command,
segment,
redact: redactSecrets,
askMode: decision === 'ask',
});
const output: HookOutput = {
hookSpecificOutput: {
hookEventName: 'PreToolUse',
permissionDecision: decision,
permissionDecisionReason: message,
},
};
console.log(JSON.stringify(output));
}
export async function runClaudeCodeHook(): Promise<void> {
const chunks: Buffer[] = [];
for await (const chunk of process.stdin) {
chunks.push(chunk as Buffer);
}
const inputText = Buffer.concat(chunks).toString('utf-8').trim();
if (!inputText) {
return;
}
let input: HookInput;
try {
input = JSON.parse(inputText) as HookInput;
} catch {
if (envTruthy('SAFETY_NET_STRICT')) {
outputDecision('deny', 'Failed to parse hook input JSON (strict mode)');
}
return;
}
if (input.tool_name !== 'Bash') {
return;
}
const command = input.tool_input?.command;
if (!command) {
return;
}
const cwd = input.cwd ?? process.cwd();
const strict = envTruthy('SAFETY_NET_STRICT');
const askMode = envTruthy('SAFETY_NET_ASK');
const paranoidAll = envTruthy('SAFETY_NET_PARANOID');
const paranoidRm = paranoidAll || envTruthy('SAFETY_NET_PARANOID_RM');
const paranoidInterpreters = paranoidAll || envTruthy('SAFETY_NET_PARANOID_INTERPRETERS');
const config = loadConfig(cwd);
const result = analyzeCommand(command, {
cwd,
config,
strict,
paranoidRm,
paranoidInterpreters,
});
if (result) {
const sessionId = input.session_id;
if (sessionId) {
writeAuditLog(sessionId, command, result.segment, result.reason, cwd);
}
outputDecision(askMode && !strict ? 'ask' : 'deny', result.reason, command, result.segment);
}
}