@massu/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
3
+
4
+ // src/hooks/security-gate.ts
5
+ var DANGEROUS_BASH_PATTERNS = [
6
+ { pattern: /rm\s+-[a-z]*r[a-z]*f[a-z]*\s+\/(?:\s|$)/, label: "rm -rf /" },
7
+ { pattern: /rm\s+-[a-z]*f[a-z]*r[a-z]*\s+\/(?:\s|$)/, label: "rm -rf /" },
8
+ { pattern: /curl\s+.*\|\s*(?:bash|sh|zsh)/, label: "curl | bash (remote code execution)" },
9
+ { pattern: /wget\s+.*\|\s*(?:bash|sh|zsh)/, label: "wget | bash (remote code execution)" },
10
+ { pattern: /chmod\s+777/, label: "chmod 777 (world-writable permissions)" },
11
+ { pattern: /chmod\s+-R\s+777/, label: "chmod -R 777 (world-writable permissions)" },
12
+ { pattern: />\s*\/etc\/passwd/, label: "write to /etc/passwd" },
13
+ { pattern: />\s*\/etc\/shadow/, label: "write to /etc/shadow" },
14
+ { pattern: />\s*\/etc\/sudoers/, label: "write to /etc/sudoers" },
15
+ { pattern: /dd\s+if=.*of=\/dev\/(?:sda|sdb|hda|hdb|nvme)/, label: "dd to raw device" },
16
+ { pattern: /mkfs\s+\/dev\//, label: "format disk device" },
17
+ { pattern: /:\(\)\s*\{\s*:\|:\s*&\s*\}/, label: "fork bomb" },
18
+ { pattern: /eval\s+.*\$\(.*curl/, label: "eval with remote curl" },
19
+ { pattern: /base64\s+-d\s+.*\|\s*(?:bash|sh|zsh)/, label: "base64 decoded shell exec" }
20
+ ];
21
+ var PROTECTED_FILE_PATTERNS = [
22
+ { pattern: /\.env$/, label: ".env file" },
23
+ { pattern: /\.env\./, label: ".env.* file" },
24
+ { pattern: /credentials(?:\.json)?$/, label: "credentials file" },
25
+ { pattern: /\.pem$/, label: ".pem certificate/key file" },
26
+ { pattern: /\.key$/, label: ".key file" },
27
+ { pattern: /\.p12$/, label: ".p12 keystore file" },
28
+ { pattern: /\.pfx$/, label: ".pfx keystore file" },
29
+ { pattern: /id_rsa$/, label: "RSA private key" },
30
+ { pattern: /id_ed25519$/, label: "Ed25519 private key" },
31
+ { pattern: /id_ecdsa$/, label: "ECDSA private key" },
32
+ { pattern: /\.ssh\/config$/, label: "SSH config file" },
33
+ { pattern: /secrets\.yaml$/, label: "secrets.yaml file" },
34
+ { pattern: /secrets\.yml$/, label: "secrets.yml file" },
35
+ { pattern: /\.netrc$/, label: ".netrc credentials file" },
36
+ { pattern: /aws\/credentials$/, label: "AWS credentials file" },
37
+ { pattern: /kubeconfig$/, label: "Kubernetes config file" }
38
+ ];
39
+ function checkBashCommand(command) {
40
+ for (const { pattern, label } of DANGEROUS_BASH_PATTERNS) {
41
+ if (pattern.test(command)) {
42
+ return label;
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+ function checkFilePath(filePath) {
48
+ for (const { pattern, label } of PROTECTED_FILE_PATTERNS) {
49
+ if (pattern.test(filePath)) {
50
+ return label;
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ async function main() {
56
+ try {
57
+ const input = await readStdin();
58
+ const hookInput = JSON.parse(input);
59
+ const { tool_name, tool_input } = hookInput;
60
+ if (tool_name === "Bash" && tool_input.command) {
61
+ const violation = checkBashCommand(tool_input.command);
62
+ if (violation) {
63
+ process.stdout.write(JSON.stringify({
64
+ message: `SECURITY GATE: Dangerous command pattern detected: ${violation}
65
+ Command: ${tool_input.command.slice(0, 200)}
66
+ Review carefully before proceeding.`
67
+ }));
68
+ }
69
+ }
70
+ if ((tool_name === "Write" || tool_name === "Edit") && tool_input.file_path) {
71
+ const violation = checkFilePath(tool_input.file_path);
72
+ if (violation) {
73
+ process.stdout.write(JSON.stringify({
74
+ message: `SECURITY GATE: Attempt to write to protected file: ${violation}
75
+ Path: ${tool_input.file_path}
76
+ Ensure this is intentional and no secrets will be exposed.`
77
+ }));
78
+ }
79
+ }
80
+ } catch {
81
+ }
82
+ process.exit(0);
83
+ }
84
+ function readStdin() {
85
+ return new Promise((resolve) => {
86
+ let data = "";
87
+ process.stdin.setEncoding("utf-8");
88
+ process.stdin.on("data", (chunk) => {
89
+ data += chunk;
90
+ });
91
+ process.stdin.on("end", () => resolve(data));
92
+ setTimeout(() => resolve(data), 400);
93
+ });
94
+ }
95
+ main();