@solongate/proxy 0.36.0 → 0.37.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 +22 -36
- package/dist/lib.js +22 -36
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5640,39 +5640,34 @@ var PolicySyncManager = class {
|
|
|
5640
5640
|
};
|
|
5641
5641
|
|
|
5642
5642
|
// src/ai-judge.ts
|
|
5643
|
-
var SYSTEM_PROMPT = `You are a security judge for an AI coding tool.
|
|
5643
|
+
var SYSTEM_PROMPT = `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.
|
|
5644
5644
|
|
|
5645
5645
|
You will receive a JSON object with:
|
|
5646
5646
|
- "tool": the tool name being called
|
|
5647
5647
|
- "arguments": the tool's arguments
|
|
5648
|
-
- "protected_files": EXACT list of
|
|
5649
|
-
- "protected_paths": EXACT list of directories
|
|
5650
|
-
- "denied_actions": list of actions that are never allowed
|
|
5648
|
+
- "protected_files": the EXACT and COMPLETE list of protected files from the user's policy
|
|
5649
|
+
- "protected_paths": the EXACT and COMPLETE list of protected directories from the user's policy
|
|
5651
5650
|
|
|
5652
|
-
|
|
5651
|
+
RULES:
|
|
5652
|
+
1. DENY ONLY if the tool call could access a file or path that is in protected_files or protected_paths.
|
|
5653
|
+
2. ALLOW everything else. You must NOT invent your own security rules.
|
|
5654
|
+
3. If a file is NOT in protected_files, it is NOT protected \u2014 even if the filename looks sensitive.
|
|
5655
|
+
4. "cat test.txt" is ALLOWED if test.txt is not in protected_files.
|
|
5656
|
+
5. "curl https://example.com" is ALLOWED unless it sends protected file content.
|
|
5657
|
+
6. "printenv" is ALLOWED unless the policy explicitly protects it.
|
|
5653
5658
|
|
|
5654
|
-
DENY if the
|
|
5655
|
-
- Shell glob patterns
|
|
5656
|
-
- Command substitution
|
|
5657
|
-
-
|
|
5658
|
-
-
|
|
5659
|
-
-
|
|
5660
|
-
-
|
|
5661
|
-
- Any
|
|
5659
|
+
BYPASS DETECTION \u2014 DENY if the command accesses a protected file through:
|
|
5660
|
+
- Shell glob patterns: "cat cred*" could match "credentials.json" IF it is in protected_files
|
|
5661
|
+
- Command substitution: "cat $(echo .env)" builds ".env"
|
|
5662
|
+
- Variable interpolation: f=".en"; cat \${f}v builds ".env"
|
|
5663
|
+
- Process substitution: <(cat .env)
|
|
5664
|
+
- Multi-stage: cp protected_file /tmp/x && cat /tmp/x
|
|
5665
|
+
- Input redirection: < .env
|
|
5666
|
+
- Any file-reading utility (cat, head, tail, less, perl, awk, sed, xxd, etc.)
|
|
5662
5667
|
|
|
5663
|
-
|
|
5664
|
-
- The command sends data to external URLs (curl -d, wget --post)
|
|
5665
|
-
- The command leaks environment variables (printenv, env, process.env)
|
|
5666
|
-
- The command executes remotely downloaded code (curl|bash)
|
|
5668
|
+
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.
|
|
5667
5669
|
|
|
5668
|
-
|
|
5669
|
-
- The file is NOT in protected_files \u2014 even if cat, head, etc. is used. Reading non-protected files is normal.
|
|
5670
|
-
- The action is a normal development operation (ls, git status, npm build, cat app.js, etc.)
|
|
5671
|
-
- The action does not touch any protected file or path
|
|
5672
|
-
|
|
5673
|
-
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. Do NOT over-block.
|
|
5674
|
-
|
|
5675
|
-
Respond with ONLY valid JSON, no markdown, no explanation outside the JSON:
|
|
5670
|
+
Respond with ONLY valid JSON:
|
|
5676
5671
|
{"decision": "ALLOW" or "DENY", "reason": "brief one-line explanation", "confidence": 0.0 to 1.0}`;
|
|
5677
5672
|
var AuthError = class extends Error {
|
|
5678
5673
|
constructor(message) {
|
|
@@ -5684,24 +5679,16 @@ var AiJudge = class _AiJudge {
|
|
|
5684
5679
|
config;
|
|
5685
5680
|
protectedFiles;
|
|
5686
5681
|
protectedPaths;
|
|
5687
|
-
deniedActions;
|
|
5688
5682
|
isOllamaEndpoint;
|
|
5689
5683
|
// Circuit breaker: after 3 consecutive failures in 60s, skip AI Judge
|
|
5690
5684
|
consecutiveFailures = 0;
|
|
5691
5685
|
lastFailureTime = 0;
|
|
5692
5686
|
static CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
5693
5687
|
static CIRCUIT_BREAKER_RESET_MS = 6e4;
|
|
5694
|
-
constructor(config, protectedFiles, protectedPaths
|
|
5695
|
-
"file deletion",
|
|
5696
|
-
"data exfiltration",
|
|
5697
|
-
"remote code execution",
|
|
5698
|
-
"environment variable leak",
|
|
5699
|
-
"security control bypass"
|
|
5700
|
-
]) {
|
|
5688
|
+
constructor(config, protectedFiles, protectedPaths) {
|
|
5701
5689
|
this.config = config;
|
|
5702
5690
|
this.protectedFiles = protectedFiles;
|
|
5703
5691
|
this.protectedPaths = protectedPaths;
|
|
5704
|
-
this.deniedActions = deniedActions;
|
|
5705
5692
|
this.isOllamaEndpoint = config.endpoint.includes("11434") || config.endpoint.includes("ollama");
|
|
5706
5693
|
}
|
|
5707
5694
|
/**
|
|
@@ -5725,8 +5712,7 @@ var AiJudge = class _AiJudge {
|
|
|
5725
5712
|
tool: toolName,
|
|
5726
5713
|
arguments: sanitizedArgs,
|
|
5727
5714
|
protected_files: this.protectedFiles,
|
|
5728
|
-
protected_paths: this.protectedPaths
|
|
5729
|
-
denied_actions: this.deniedActions
|
|
5715
|
+
protected_paths: this.protectedPaths
|
|
5730
5716
|
});
|
|
5731
5717
|
try {
|
|
5732
5718
|
const response = await this.callLLM(userMessage);
|
package/dist/lib.js
CHANGED
|
@@ -3939,39 +3939,34 @@ var PolicySyncManager = class {
|
|
|
3939
3939
|
};
|
|
3940
3940
|
|
|
3941
3941
|
// src/ai-judge.ts
|
|
3942
|
-
var SYSTEM_PROMPT = `You are a security judge for an AI coding tool.
|
|
3942
|
+
var SYSTEM_PROMPT = `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.
|
|
3943
3943
|
|
|
3944
3944
|
You will receive a JSON object with:
|
|
3945
3945
|
- "tool": the tool name being called
|
|
3946
3946
|
- "arguments": the tool's arguments
|
|
3947
|
-
- "protected_files": EXACT list of
|
|
3948
|
-
- "protected_paths": EXACT list of directories
|
|
3949
|
-
- "denied_actions": list of actions that are never allowed
|
|
3947
|
+
- "protected_files": the EXACT and COMPLETE list of protected files from the user's policy
|
|
3948
|
+
- "protected_paths": the EXACT and COMPLETE list of protected directories from the user's policy
|
|
3950
3949
|
|
|
3951
|
-
|
|
3950
|
+
RULES:
|
|
3951
|
+
1. DENY ONLY if the tool call could access a file or path that is in protected_files or protected_paths.
|
|
3952
|
+
2. ALLOW everything else. You must NOT invent your own security rules.
|
|
3953
|
+
3. If a file is NOT in protected_files, it is NOT protected \u2014 even if the filename looks sensitive.
|
|
3954
|
+
4. "cat test.txt" is ALLOWED if test.txt is not in protected_files.
|
|
3955
|
+
5. "curl https://example.com" is ALLOWED unless it sends protected file content.
|
|
3956
|
+
6. "printenv" is ALLOWED unless the policy explicitly protects it.
|
|
3952
3957
|
|
|
3953
|
-
DENY if the
|
|
3954
|
-
- Shell glob patterns
|
|
3955
|
-
- Command substitution
|
|
3956
|
-
-
|
|
3957
|
-
-
|
|
3958
|
-
-
|
|
3959
|
-
-
|
|
3960
|
-
- Any
|
|
3958
|
+
BYPASS DETECTION \u2014 DENY if the command accesses a protected file through:
|
|
3959
|
+
- Shell glob patterns: "cat cred*" could match "credentials.json" IF it is in protected_files
|
|
3960
|
+
- Command substitution: "cat $(echo .env)" builds ".env"
|
|
3961
|
+
- Variable interpolation: f=".en"; cat \${f}v builds ".env"
|
|
3962
|
+
- Process substitution: <(cat .env)
|
|
3963
|
+
- Multi-stage: cp protected_file /tmp/x && cat /tmp/x
|
|
3964
|
+
- Input redirection: < .env
|
|
3965
|
+
- Any file-reading utility (cat, head, tail, less, perl, awk, sed, xxd, etc.)
|
|
3961
3966
|
|
|
3962
|
-
|
|
3963
|
-
- The command sends data to external URLs (curl -d, wget --post)
|
|
3964
|
-
- The command leaks environment variables (printenv, env, process.env)
|
|
3965
|
-
- The command executes remotely downloaded code (curl|bash)
|
|
3967
|
+
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.
|
|
3966
3968
|
|
|
3967
|
-
|
|
3968
|
-
- The file is NOT in protected_files \u2014 even if cat, head, etc. is used. Reading non-protected files is normal.
|
|
3969
|
-
- The action is a normal development operation (ls, git status, npm build, cat app.js, etc.)
|
|
3970
|
-
- The action does not touch any protected file or path
|
|
3971
|
-
|
|
3972
|
-
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. Do NOT over-block.
|
|
3973
|
-
|
|
3974
|
-
Respond with ONLY valid JSON, no markdown, no explanation outside the JSON:
|
|
3969
|
+
Respond with ONLY valid JSON:
|
|
3975
3970
|
{"decision": "ALLOW" or "DENY", "reason": "brief one-line explanation", "confidence": 0.0 to 1.0}`;
|
|
3976
3971
|
var AuthError = class extends Error {
|
|
3977
3972
|
constructor(message) {
|
|
@@ -3983,24 +3978,16 @@ var AiJudge = class _AiJudge {
|
|
|
3983
3978
|
config;
|
|
3984
3979
|
protectedFiles;
|
|
3985
3980
|
protectedPaths;
|
|
3986
|
-
deniedActions;
|
|
3987
3981
|
isOllamaEndpoint;
|
|
3988
3982
|
// Circuit breaker: after 3 consecutive failures in 60s, skip AI Judge
|
|
3989
3983
|
consecutiveFailures = 0;
|
|
3990
3984
|
lastFailureTime = 0;
|
|
3991
3985
|
static CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
3992
3986
|
static CIRCUIT_BREAKER_RESET_MS = 6e4;
|
|
3993
|
-
constructor(config, protectedFiles, protectedPaths
|
|
3994
|
-
"file deletion",
|
|
3995
|
-
"data exfiltration",
|
|
3996
|
-
"remote code execution",
|
|
3997
|
-
"environment variable leak",
|
|
3998
|
-
"security control bypass"
|
|
3999
|
-
]) {
|
|
3987
|
+
constructor(config, protectedFiles, protectedPaths) {
|
|
4000
3988
|
this.config = config;
|
|
4001
3989
|
this.protectedFiles = protectedFiles;
|
|
4002
3990
|
this.protectedPaths = protectedPaths;
|
|
4003
|
-
this.deniedActions = deniedActions;
|
|
4004
3991
|
this.isOllamaEndpoint = config.endpoint.includes("11434") || config.endpoint.includes("ollama");
|
|
4005
3992
|
}
|
|
4006
3993
|
/**
|
|
@@ -4024,8 +4011,7 @@ var AiJudge = class _AiJudge {
|
|
|
4024
4011
|
tool: toolName,
|
|
4025
4012
|
arguments: sanitizedArgs,
|
|
4026
4013
|
protected_files: this.protectedFiles,
|
|
4027
|
-
protected_paths: this.protectedPaths
|
|
4028
|
-
denied_actions: this.deniedActions
|
|
4014
|
+
protected_paths: this.protectedPaths
|
|
4029
4015
|
});
|
|
4030
4016
|
try {
|
|
4031
4017
|
const response = await this.callLLM(userMessage);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.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": {
|