@golproductions/check 1.3.2 → 1.3.4
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.
- package/package.json +1 -1
- package/src/index.js +40 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golproductions/check",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "Pre-execution firewall hook for AI agents. Validates every command before it reaches the shell. 152 failed commands without Check. 1 with it. Supports Claude Code, Gemini CLI, Antigravity, Cursor, and VS Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"check": "src/index.js"
|
package/src/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
|
|
9
|
-
const VERSION = "1.3.
|
|
9
|
+
const VERSION = "1.3.4";
|
|
10
10
|
const API = "https://triage.golproductions.com/preflight";
|
|
11
11
|
const LOG_API = "https://triage.golproductions.com/log";
|
|
12
12
|
const CLIENT_ID = process.env.GOL_CLIENT_ID || "";
|
|
@@ -155,7 +155,7 @@ function binaryExists(base) {
|
|
|
155
155
|
} catch { return false; }
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
function respond(platform, allowed, reason) {
|
|
158
|
+
async function respond(platform, allowed, reason) {
|
|
159
159
|
if (allowed) {
|
|
160
160
|
const out = {
|
|
161
161
|
cursor: { permission: "allow" },
|
|
@@ -163,10 +163,12 @@ function respond(platform, allowed, reason) {
|
|
|
163
163
|
claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow" } }
|
|
164
164
|
};
|
|
165
165
|
process.stdout.write(JSON.stringify(out[platform]));
|
|
166
|
+
await _logPromise;
|
|
166
167
|
process.exit(0);
|
|
167
168
|
}
|
|
168
169
|
if (platform === "gemini") {
|
|
169
170
|
process.stderr.write(reason + "\n");
|
|
171
|
+
await _logPromise;
|
|
170
172
|
process.exit(2);
|
|
171
173
|
}
|
|
172
174
|
const out = {
|
|
@@ -174,9 +176,12 @@ function respond(platform, allowed, reason) {
|
|
|
174
176
|
claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } }
|
|
175
177
|
};
|
|
176
178
|
process.stdout.write(JSON.stringify(out[platform]));
|
|
179
|
+
await _logPromise;
|
|
177
180
|
process.exit(0);
|
|
178
181
|
}
|
|
179
182
|
|
|
183
|
+
let _logPromise = Promise.resolve();
|
|
184
|
+
|
|
180
185
|
function logEvent(event) {
|
|
181
186
|
if (!CLIENT_ID) return;
|
|
182
187
|
const log = {
|
|
@@ -190,7 +195,7 @@ function logEvent(event) {
|
|
|
190
195
|
if (event.verdict === "deny") {
|
|
191
196
|
log.tokens_saved_est = 6000;
|
|
192
197
|
}
|
|
193
|
-
fetch(LOG_API, {
|
|
198
|
+
_logPromise = fetch(LOG_API, {
|
|
194
199
|
method: "POST",
|
|
195
200
|
headers: {
|
|
196
201
|
"Content-Type": "application/json",
|
|
@@ -209,22 +214,46 @@ async function main() {
|
|
|
209
214
|
input = input.replace(/^/, "").trim();
|
|
210
215
|
|
|
211
216
|
let parsed;
|
|
212
|
-
try { parsed = JSON.parse(input); } catch {
|
|
217
|
+
try { parsed = JSON.parse(input); } catch {
|
|
218
|
+
logEvent({ verdict: "allow", reason: "parse_failed", binary: "", platform, cmd: input.slice(0, 100) });
|
|
219
|
+
respond("claude", true);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
213
222
|
|
|
214
223
|
platform = detectPlatform(parsed);
|
|
215
224
|
const command = extractCommand(parsed, platform);
|
|
216
|
-
if (!command) {
|
|
225
|
+
if (!command) {
|
|
226
|
+
logEvent({ verdict: "allow", reason: "no_command", binary: "", platform, cmd: "" });
|
|
227
|
+
respond(platform, true);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
217
230
|
|
|
218
231
|
const trimmed = command.trim();
|
|
219
232
|
const first = trimmed.split(/\s+/)[0];
|
|
220
233
|
|
|
221
|
-
if (SKIP.has(first)) {
|
|
234
|
+
if (SKIP.has(first)) {
|
|
235
|
+
logEvent({ verdict: "allow", reason: "skip_builtin", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
236
|
+
respond(platform, true);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
222
239
|
|
|
223
240
|
const toolName = parsed.tool_name;
|
|
224
241
|
if (toolName === "PowerShell") {
|
|
225
|
-
if (first.startsWith("$") || first.startsWith("(") || first.startsWith("[") || first.startsWith("@")) {
|
|
226
|
-
|
|
227
|
-
|
|
242
|
+
if (first.startsWith("$") || first.startsWith("(") || first.startsWith("[") || first.startsWith("@")) {
|
|
243
|
+
logEvent({ verdict: "allow", reason: "ps_syntax", binary: first.slice(0, 30), platform, cmd: trimmed.slice(0, 100) });
|
|
244
|
+
respond(platform, true);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (PS_KEYWORDS.has(first)) {
|
|
248
|
+
logEvent({ verdict: "allow", reason: "ps_keyword", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
249
|
+
respond(platform, true);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (PS_VERB_PREFIXES.some(p => first.startsWith(p))) {
|
|
253
|
+
logEvent({ verdict: "allow", reason: "ps_cmdlet", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
254
|
+
respond(platform, true);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
228
257
|
}
|
|
229
258
|
|
|
230
259
|
if (!CLIENT_ID) {
|
|
@@ -269,7 +298,8 @@ async function main() {
|
|
|
269
298
|
logEvent({ verdict: "deny", reason: "api_rejected", binary: base, platform, cmd: trimmed.slice(0, 100) });
|
|
270
299
|
respond(platform, false, "Check: command is invalid");
|
|
271
300
|
}
|
|
272
|
-
} catch {
|
|
301
|
+
} catch (e) {
|
|
302
|
+
logEvent({ verdict: "allow", reason: "error_fallback", binary: "", platform, cmd: String(e).slice(0, 100) });
|
|
273
303
|
respond(platform, true);
|
|
274
304
|
}
|
|
275
305
|
}
|