@solongate/proxy 0.37.0 → 0.38.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.
Files changed (2) hide show
  1. package/hooks/guard.mjs +32 -37
  2. package/package.json +1 -1
package/hooks/guard.mjs CHANGED
@@ -1134,7 +1134,9 @@ process.stdin.on('end', async () => {
1134
1134
 
1135
1135
  // ── AI Judge: semantic intent analysis (runs when policy ALLOWs) ──
1136
1136
  if (!reason) {
1137
- const GROQ_KEY = process.env.GROQ_API_KEY || dotenv.GROQ_API_KEY || '';
1137
+ let GROQ_KEY = process.env.GROQ_API_KEY || dotenv.GROQ_API_KEY || '';
1138
+ // Skip placeholder values
1139
+ if (GROQ_KEY && (GROQ_KEY.includes('your_') || GROQ_KEY.includes('_here') || GROQ_KEY.length < 10)) GROQ_KEY = '';
1138
1140
  let aiJudgeEnabled = false;
1139
1141
  let aiJudgeModel = 'llama-3.1-8b-instant';
1140
1142
  let aiJudgeEndpoint = 'https://api.groq.com/openai';
@@ -1197,40 +1199,34 @@ process.stdin.on('end', async () => {
1197
1199
  arguments: args,
1198
1200
  protected_files: protectedFiles,
1199
1201
  protected_paths: protectedPathsList,
1200
- denied_actions: ['file deletion', 'data exfiltration', 'remote code execution', 'environment variable leak', 'security control bypass'],
1201
1202
  });
1202
1203
 
1203
- const systemPrompt = `You are a security judge for an AI coding tool. You evaluate tool calls and decide if they should be ALLOWED or DENIED.
1204
+ const systemPrompt = `You are a security judge for an AI coding tool. Your ONLY job is to check if a tool call accesses files or paths that are in the protected lists. Nothing else.
1204
1205
 
1205
1206
  You will receive a JSON object with:
1206
- - "tool": the tool name being called (e.g., Bash, Write, Read, Edit)
1207
+ - "tool": the tool name being called
1207
1208
  - "arguments": the tool's arguments
1208
- - "protected_files": EXACT list of files that must NEVER be accessed. ONLY these specific files are protected nothing else.
1209
- - "protected_paths": EXACT list of directories that must NEVER be accessed. ONLY these specific paths are protected — nothing else.
1210
- - "denied_actions": list of actions that are never allowed
1211
-
1212
- IMPORTANT: You must ONLY protect files and paths that are EXPLICITLY listed in protected_files and protected_paths. If a file is NOT in the list, it is NOT protected and access should be ALLOWED. Do NOT invent or assume additional protected files.
1213
-
1214
- DENY if the tool call could, directly or indirectly, access a file from the protected_files list — even through:
1215
- - Shell glob patterns (e.g., "cred*" could match "credentials.json" IF credentials.json is in protected_files)
1216
- - Command substitution ($(...), backticks)
1217
- - Process substitution (<(cat file)) check inside <(...) for protected files
1218
- - Variable interpolation (e.g., f=".en"; cat \${f}v builds ".env" — DENY only if .env is in protected_files)
1219
- - Input redirection (< file)
1220
- - Multi-stage operations: tar/cp a protected file then read the copy DENY the entire chain
1221
- - Any utility that reads file content (cat, head, tail, less, perl, awk, sed, xxd, od, strings, dd, etc.)
1222
-
1223
- Also DENY if:
1224
- - The command sends data to external URLs (curl -d, wget --post)
1225
- - The command leaks environment variables (printenv, env, process.env)
1226
- - The command executes remotely downloaded code (curl|bash)
1227
-
1228
- ALLOW if:
1229
- - The file is NOT in protected_files — even if cat, head, etc. is used. Reading non-protected files is normal.
1230
- - The action is a normal development operation (ls, git status, npm build, cat app.js, etc.)
1231
- - The action does not touch any protected file or path
1232
-
1233
- CRITICAL: Only DENY access to files EXPLICITLY in the protected_files list. "cat app.js" is ALLOWED if app.js is not in protected_files. "cat package.json" is ALLOWED if package.json is not in protected_files. Do NOT over-block.
1209
+ - "protected_files": the EXACT and COMPLETE list of protected files from the user's policy
1210
+ - "protected_paths": the EXACT and COMPLETE list of protected directories from the user's policy
1211
+
1212
+ RULES:
1213
+ 1. DENY ONLY if the tool call could access a file or path that is in protected_files or protected_paths.
1214
+ 2. ALLOW everything else. You must NOT invent your own security rules.
1215
+ 3. If a file is NOT in protected_files, it is NOT protected even if the filename looks sensitive.
1216
+ 4. "cat test.txt" is ALLOWED if test.txt is not in protected_files.
1217
+ 5. "curl https://example.com" is ALLOWED unless it sends protected file content.
1218
+ 6. "printenv" is ALLOWED unless the policy explicitly protects it.
1219
+
1220
+ BYPASS DETECTION DENY if the command accesses a protected file through:
1221
+ - Shell glob patterns: "cat cred*" could match "credentials.json" IF it is in protected_files
1222
+ - Command substitution: "cat $(echo .env)" builds ".env"
1223
+ - Variable interpolation: f=".en"; cat \${f}v builds ".env"
1224
+ - Process substitution: <(cat .env)
1225
+ - Multi-stage: cp protected_file /tmp/x && cat /tmp/x
1226
+ - Input redirection: < .env
1227
+ - Any file-reading utility (cat, head, tail, less, perl, awk, sed, xxd, etc.)
1228
+
1229
+ CRITICAL: You have NO security opinions of your own. You ONLY enforce the protected_files and protected_paths lists. If something is not in those lists, it is ALLOWED. Do NOT over-block.
1234
1230
 
1235
1231
  Respond with ONLY valid JSON: {"decision": "ALLOW" or "DENY", "reason": "brief explanation", "confidence": 0.0 to 1.0}`;
1236
1232
 
@@ -1258,17 +1254,16 @@ Respond with ONLY valid JSON: {"decision": "ALLOW" or "DENY", "reason": "brief e
1258
1254
  const jsonMatch = content.match(/\{[\s\S]*\}/);
1259
1255
  if (jsonMatch) {
1260
1256
  const verdict = JSON.parse(jsonMatch[0]);
1261
- if (verdict.decision === 'DENY') {
1257
+ if (verdict.decision === 'DENY' && verdict.confidence >= 0.7) {
1262
1258
  reason = '[SolonGate AI Judge] Blocked: ' + (verdict.reason || 'Semantic analysis detected a policy violation');
1263
1259
  }
1260
+ // Low-confidence DENY or ALLOW → skip (don't block)
1264
1261
  }
1265
- } else {
1266
- // Fail-closed: LLM error → DENY
1267
- reason = '[SolonGate AI Judge] Blocked: Groq API error (fail-closed)';
1268
1262
  }
1269
- } catch (err) {
1270
- // Fail-closed: timeout or parse error DENY
1271
- reason = '[SolonGate AI Judge] Blocked: ' + (err.message || 'error') + ' (fail-closed)';
1263
+ // Auth/config errors (401, 403) → skip AI Judge, don't DENY
1264
+ // Other LLM errors skip too (policy engine already evaluated)
1265
+ } catch {
1266
+ // Timeout or parse error → skip AI Judge (policy engine already passed)
1272
1267
  }
1273
1268
  }
1274
1269
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.37.0",
3
+ "version": "0.38.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": {