@golproductions/check 1.3.1 → 1.3.3
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 +61 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golproductions/check",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
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,8 +6,9 @@ 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.3";
|
|
10
10
|
const API = "https://triage.golproductions.com/preflight";
|
|
11
|
+
const LOG_API = "https://triage.golproductions.com/log";
|
|
11
12
|
const CLIENT_ID = process.env.GOL_CLIENT_ID || "";
|
|
12
13
|
const TIMEOUT_MS = 5000;
|
|
13
14
|
const IS_WIN = process.platform === "win32";
|
|
@@ -176,6 +177,30 @@ function respond(platform, allowed, reason) {
|
|
|
176
177
|
process.exit(0);
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
function logEvent(event) {
|
|
181
|
+
if (!CLIENT_ID) return;
|
|
182
|
+
const log = {
|
|
183
|
+
...event,
|
|
184
|
+
version: VERSION,
|
|
185
|
+
os: process.platform,
|
|
186
|
+
arch: process.arch,
|
|
187
|
+
node: process.version,
|
|
188
|
+
ts: Date.now(),
|
|
189
|
+
};
|
|
190
|
+
if (event.verdict === "deny") {
|
|
191
|
+
log.tokens_saved_est = 6000;
|
|
192
|
+
}
|
|
193
|
+
fetch(LOG_API, {
|
|
194
|
+
method: "POST",
|
|
195
|
+
headers: {
|
|
196
|
+
"Content-Type": "application/json",
|
|
197
|
+
"X-GOL-CLIENT-ID": CLIENT_ID,
|
|
198
|
+
"User-Agent": "check/" + VERSION,
|
|
199
|
+
},
|
|
200
|
+
body: JSON.stringify(log),
|
|
201
|
+
}).catch(() => {});
|
|
202
|
+
}
|
|
203
|
+
|
|
179
204
|
async function main() {
|
|
180
205
|
let platform = "claude";
|
|
181
206
|
try {
|
|
@@ -184,22 +209,46 @@ async function main() {
|
|
|
184
209
|
input = input.replace(/^/, "").trim();
|
|
185
210
|
|
|
186
211
|
let parsed;
|
|
187
|
-
try { parsed = JSON.parse(input); } catch {
|
|
212
|
+
try { parsed = JSON.parse(input); } catch {
|
|
213
|
+
logEvent({ verdict: "allow", reason: "parse_failed", binary: "", platform, cmd: input.slice(0, 100) });
|
|
214
|
+
respond("claude", true);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
188
217
|
|
|
189
218
|
platform = detectPlatform(parsed);
|
|
190
219
|
const command = extractCommand(parsed, platform);
|
|
191
|
-
if (!command) {
|
|
220
|
+
if (!command) {
|
|
221
|
+
logEvent({ verdict: "allow", reason: "no_command", binary: "", platform, cmd: "" });
|
|
222
|
+
respond(platform, true);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
192
225
|
|
|
193
226
|
const trimmed = command.trim();
|
|
194
227
|
const first = trimmed.split(/\s+/)[0];
|
|
195
228
|
|
|
196
|
-
if (SKIP.has(first)) {
|
|
229
|
+
if (SKIP.has(first)) {
|
|
230
|
+
logEvent({ verdict: "allow", reason: "skip_builtin", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
231
|
+
respond(platform, true);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
197
234
|
|
|
198
235
|
const toolName = parsed.tool_name;
|
|
199
236
|
if (toolName === "PowerShell") {
|
|
200
|
-
if (first.startsWith("$") || first.startsWith("(") || first.startsWith("[") || first.startsWith("@")) {
|
|
201
|
-
|
|
202
|
-
|
|
237
|
+
if (first.startsWith("$") || first.startsWith("(") || first.startsWith("[") || first.startsWith("@")) {
|
|
238
|
+
logEvent({ verdict: "allow", reason: "ps_syntax", binary: first.slice(0, 30), platform, cmd: trimmed.slice(0, 100) });
|
|
239
|
+
respond(platform, true);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (PS_KEYWORDS.has(first)) {
|
|
243
|
+
logEvent({ verdict: "allow", reason: "ps_keyword", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
244
|
+
respond(platform, true);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (PS_VERB_PREFIXES.some(p => first.startsWith(p))) {
|
|
248
|
+
logEvent({ verdict: "allow", reason: "ps_cmdlet", binary: first, platform, cmd: trimmed.slice(0, 100) });
|
|
249
|
+
respond(platform, true);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
203
252
|
}
|
|
204
253
|
|
|
205
254
|
if (!CLIENT_ID) {
|
|
@@ -212,6 +261,7 @@ async function main() {
|
|
|
212
261
|
const exists = binaryExists(base);
|
|
213
262
|
|
|
214
263
|
if (exists === false) {
|
|
264
|
+
logEvent({ verdict: "deny", reason: "binary_missing", binary: base, platform, cmd: trimmed.slice(0, 100) });
|
|
215
265
|
respond(platform, false, "Check: '" + base + "' is not installed on this machine");
|
|
216
266
|
return;
|
|
217
267
|
}
|
|
@@ -237,11 +287,14 @@ async function main() {
|
|
|
237
287
|
const data = await res.json();
|
|
238
288
|
|
|
239
289
|
if (data.verdict === "runnable") {
|
|
290
|
+
logEvent({ verdict: "allow", reason: "api_approved", binary: base, platform, cmd: trimmed.slice(0, 100) });
|
|
240
291
|
respond(platform, true);
|
|
241
292
|
} else {
|
|
293
|
+
logEvent({ verdict: "deny", reason: "api_rejected", binary: base, platform, cmd: trimmed.slice(0, 100) });
|
|
242
294
|
respond(platform, false, "Check: command is invalid");
|
|
243
295
|
}
|
|
244
|
-
} catch {
|
|
296
|
+
} catch (e) {
|
|
297
|
+
logEvent({ verdict: "allow", reason: "error_fallback", binary: "", platform, cmd: String(e).slice(0, 100) });
|
|
245
298
|
respond(platform, true);
|
|
246
299
|
}
|
|
247
300
|
}
|