@solongate/proxy 0.38.0 → 0.39.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.
package/dist/index.js CHANGED
@@ -5707,6 +5707,27 @@ var AiJudge = class _AiJudge {
5707
5707
  }
5708
5708
  this.consecutiveFailures = 0;
5709
5709
  }
5710
+ const argStr = JSON.stringify(args).toLowerCase();
5711
+ const hasShellTricks = /\$[\({]|`|<\(|>\(|\beval\b|\bexec\b|\bsource\b|\bxargs\b/.test(argStr);
5712
+ const hasWildcard = /[*?]/.test(argStr);
5713
+ let couldMatchProtected = hasShellTricks || hasWildcard;
5714
+ if (!couldMatchProtected) {
5715
+ const allProtected = [...this.protectedFiles, ...this.protectedPaths];
5716
+ for (const p of allProtected) {
5717
+ const core = p.replace(/[*?[\]{}]/g, "").replace(/^\.+/, "").toLowerCase();
5718
+ if (core && core.length >= 2 && argStr.includes(core)) {
5719
+ couldMatchProtected = true;
5720
+ break;
5721
+ }
5722
+ }
5723
+ }
5724
+ if (!couldMatchProtected) {
5725
+ return {
5726
+ decision: "ALLOW",
5727
+ reason: "No protected file/path referenced in arguments",
5728
+ confidence: 1
5729
+ };
5730
+ }
5710
5731
  const sanitizedArgs = this.sanitizeArgs(args);
5711
5732
  const userMessage = JSON.stringify({
5712
5733
  tool: toolName,
package/dist/lib.js CHANGED
@@ -4006,6 +4006,27 @@ var AiJudge = class _AiJudge {
4006
4006
  }
4007
4007
  this.consecutiveFailures = 0;
4008
4008
  }
4009
+ const argStr = JSON.stringify(args).toLowerCase();
4010
+ const hasShellTricks = /\$[\({]|`|<\(|>\(|\beval\b|\bexec\b|\bsource\b|\bxargs\b/.test(argStr);
4011
+ const hasWildcard = /[*?]/.test(argStr);
4012
+ let couldMatchProtected = hasShellTricks || hasWildcard;
4013
+ if (!couldMatchProtected) {
4014
+ const allProtected = [...this.protectedFiles, ...this.protectedPaths];
4015
+ for (const p of allProtected) {
4016
+ const core = p.replace(/[*?[\]{}]/g, "").replace(/^\.+/, "").toLowerCase();
4017
+ if (core && core.length >= 2 && argStr.includes(core)) {
4018
+ couldMatchProtected = true;
4019
+ break;
4020
+ }
4021
+ }
4022
+ }
4023
+ if (!couldMatchProtected) {
4024
+ return {
4025
+ decision: "ALLOW",
4026
+ reason: "No protected file/path referenced in arguments",
4027
+ confidence: 1
4028
+ };
4029
+ }
4009
4030
  const sanitizedArgs = this.sanitizeArgs(args);
4010
4031
  const userMessage = JSON.stringify({
4011
4032
  tool: toolName,
package/hooks/guard.mjs CHANGED
@@ -1194,6 +1194,30 @@ process.stdin.on('end', async () => {
1194
1194
  }
1195
1195
  }
1196
1196
 
1197
+ // Pre-filter: skip AI Judge if tool args clearly don't touch any protected file/path.
1198
+ // Only call LLM when there's a potential match or obfuscation attempt.
1199
+ const argStr = JSON.stringify(args).toLowerCase();
1200
+ const hasShellTricks = /\$[\({]|`|<\(|>\(|\beval\b|\bexec\b|\bsource\b|\bxargs\b/.test(argStr);
1201
+ const hasWildcard = /[*?]/.test(argStr);
1202
+ let couldMatchProtected = hasShellTricks || hasWildcard;
1203
+ if (!couldMatchProtected) {
1204
+ // Check if any protected file/path name (without glob chars) appears in args
1205
+ const allProtected = [...protectedFiles, ...protectedPathsList];
1206
+ for (const p of allProtected) {
1207
+ // Strip glob chars to get the core name: "*.env*" → "env", ".solongate" → "solongate"
1208
+ const core = p.replace(/[*?[\]{}]/g, '').replace(/^\.+/, '').toLowerCase();
1209
+ if (core && core.length >= 2 && argStr.includes(core)) {
1210
+ couldMatchProtected = true;
1211
+ break;
1212
+ }
1213
+ }
1214
+ }
1215
+
1216
+ // If args clearly don't reference any protected pattern, skip LLM — instant ALLOW
1217
+ if (!couldMatchProtected) {
1218
+ // No need to call AI Judge — nothing to protect here
1219
+ } else {
1220
+
1197
1221
  const judgePayload = JSON.stringify({
1198
1222
  tool: toolName,
1199
1223
  arguments: args,
@@ -1262,6 +1286,8 @@ Respond with ONLY valid JSON: {"decision": "ALLOW" or "DENY", "reason": "brief e
1262
1286
  }
1263
1287
  // Auth/config errors (401, 403) → skip AI Judge, don't DENY
1264
1288
  // Other LLM errors → skip too (policy engine already evaluated)
1289
+
1290
+ } // end else (couldMatchProtected)
1265
1291
  } catch {
1266
1292
  // Timeout or parse error → skip AI Judge (policy engine already passed)
1267
1293
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.38.0",
3
+ "version": "0.39.0",
4
4
  "description": "AI tool security proxy — protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {