@solongate/proxy 0.53.0 → 0.54.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 +10 -1
- package/dist/shield.js +10 -1
- package/hooks/audit.mjs +12 -1
- package/hooks/guard.bundled.mjs +14 -2
- package/hooks/guard.mjs +13 -2
- package/hooks/shield.mjs +11 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7033,6 +7033,15 @@ function loadCfg() {
|
|
|
7033
7033
|
}
|
|
7034
7034
|
return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [] };
|
|
7035
7035
|
}
|
|
7036
|
+
function dlpGlobToRe(glob, flags) {
|
|
7037
|
+
let re = "";
|
|
7038
|
+
for (const ch of String(glob || "")) {
|
|
7039
|
+
if (ch === "*") re += "[^\\s]*";
|
|
7040
|
+
else if (".+?^${}()|[]\\".indexOf(ch) !== -1) re += "\\" + ch;
|
|
7041
|
+
else re += ch;
|
|
7042
|
+
}
|
|
7043
|
+
return new RegExp(re, flags);
|
|
7044
|
+
}
|
|
7036
7045
|
function redactString(s, cfg) {
|
|
7037
7046
|
if (!cfg || typeof s !== "string" || !s) return s;
|
|
7038
7047
|
const allow = new Set(cfg.patterns);
|
|
@@ -7040,7 +7049,7 @@ function redactString(s, cfg) {
|
|
|
7040
7049
|
for (const p of DLP_PATTERNS) if (allow.has(p.name)) out = out.replace(p.re, `[REDACTED: ${p.name}]`);
|
|
7041
7050
|
for (const c3 of cfg.custom) {
|
|
7042
7051
|
try {
|
|
7043
|
-
out = out.replace(
|
|
7052
|
+
out = out.replace(dlpGlobToRe(c3.re, "g"), `[REDACTED: ${c3.name || "custom"}]`);
|
|
7044
7053
|
} catch {
|
|
7045
7054
|
}
|
|
7046
7055
|
}
|
package/dist/shield.js
CHANGED
|
@@ -39,6 +39,15 @@ function loadCfg() {
|
|
|
39
39
|
}
|
|
40
40
|
return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [] };
|
|
41
41
|
}
|
|
42
|
+
function dlpGlobToRe(glob, flags) {
|
|
43
|
+
let re = "";
|
|
44
|
+
for (const ch of String(glob || "")) {
|
|
45
|
+
if (ch === "*") re += "[^\\s]*";
|
|
46
|
+
else if (".+?^${}()|[]\\".indexOf(ch) !== -1) re += "\\" + ch;
|
|
47
|
+
else re += ch;
|
|
48
|
+
}
|
|
49
|
+
return new RegExp(re, flags);
|
|
50
|
+
}
|
|
42
51
|
function redactString(s, cfg) {
|
|
43
52
|
if (!cfg || typeof s !== "string" || !s) return s;
|
|
44
53
|
const allow = new Set(cfg.patterns);
|
|
@@ -46,7 +55,7 @@ function redactString(s, cfg) {
|
|
|
46
55
|
for (const p of DLP_PATTERNS) if (allow.has(p.name)) out = out.replace(p.re, `[REDACTED: ${p.name}]`);
|
|
47
56
|
for (const c of cfg.custom) {
|
|
48
57
|
try {
|
|
49
|
-
out = out.replace(
|
|
58
|
+
out = out.replace(dlpGlobToRe(c.re, "g"), `[REDACTED: ${c.name || "custom"}]`);
|
|
50
59
|
} catch {
|
|
51
60
|
}
|
|
52
61
|
}
|
package/hooks/audit.mjs
CHANGED
|
@@ -206,6 +206,17 @@ function loadDlpRedact() {
|
|
|
206
206
|
|
|
207
207
|
// Replace every secret match with a labelled placeholder. cfg = { patterns:
|
|
208
208
|
// string[] (enabled built-in names), custom: {name,re}[] }.
|
|
209
|
+
// Custom patterns are GLOBs: `*` = any run of non-whitespace (so a fragment
|
|
210
|
+
// matches a whole token), same wildcard mechanic as policy/ghost.
|
|
211
|
+
function dlpGlobToRe(glob, flags) {
|
|
212
|
+
let re = '';
|
|
213
|
+
for (const ch of String(glob || '')) {
|
|
214
|
+
if (ch === '*') re += '[^\\s]*';
|
|
215
|
+
else if ('.+?^${}()|[]\\'.indexOf(ch) !== -1) re += '\\' + ch;
|
|
216
|
+
else re += ch;
|
|
217
|
+
}
|
|
218
|
+
return new RegExp(re, flags);
|
|
219
|
+
}
|
|
209
220
|
function dlpRedactText(text, cfg) {
|
|
210
221
|
if (!cfg || typeof text !== 'string' || !text) return text;
|
|
211
222
|
const allow = new Set(Array.isArray(cfg.patterns) ? cfg.patterns : []);
|
|
@@ -214,7 +225,7 @@ function dlpRedactText(text, cfg) {
|
|
|
214
225
|
if (allow.has(p.name)) out = out.replace(p.re, '[REDACTED:' + p.name + ']');
|
|
215
226
|
}
|
|
216
227
|
for (const c of Array.isArray(cfg.custom) ? cfg.custom : []) {
|
|
217
|
-
try { out = out.replace(
|
|
228
|
+
try { out = out.replace(dlpGlobToRe(c.re, 'g'), '[REDACTED:' + (c.name || 'custom') + ']'); } catch { /* skip invalid */ }
|
|
218
229
|
}
|
|
219
230
|
return out;
|
|
220
231
|
}
|
package/hooks/guard.bundled.mjs
CHANGED
|
@@ -6535,7 +6535,7 @@ import { resolve, join } from "node:path";
|
|
|
6535
6535
|
import { homedir } from "node:os";
|
|
6536
6536
|
import { gunzipSync } from "node:zlib";
|
|
6537
6537
|
import { createHash } from "node:crypto";
|
|
6538
|
-
var HOOK_VERSION =
|
|
6538
|
+
var HOOK_VERSION = 19;
|
|
6539
6539
|
var MAX_FILE_READ = 1024 * 1024;
|
|
6540
6540
|
function safeReadFileSync(filePath, encoding = "utf-8") {
|
|
6541
6541
|
try {
|
|
@@ -7010,6 +7010,18 @@ var DLP_PATTERNS = [
|
|
|
7010
7010
|
{ name: "Bearer token", re: /bearer\s+[A-Za-z0-9._-]{20,}/i },
|
|
7011
7011
|
{ name: "secret assignment", re: /(api[_-]?key|secret|token|password|passwd|access[_-]?key)["']?\s*[:=]\s*["']?[A-Za-z0-9/+_.-]{12,}/i }
|
|
7012
7012
|
];
|
|
7013
|
+
function dlpGlobToRe(glob) {
|
|
7014
|
+
let re = "";
|
|
7015
|
+
for (const ch of String(glob || "")) {
|
|
7016
|
+
if (ch === "*")
|
|
7017
|
+
re += "[^\\s]*";
|
|
7018
|
+
else if (".+?^${}()|[]\\".indexOf(ch) !== -1)
|
|
7019
|
+
re += "\\" + ch;
|
|
7020
|
+
else
|
|
7021
|
+
re += ch;
|
|
7022
|
+
}
|
|
7023
|
+
return new RegExp(re);
|
|
7024
|
+
}
|
|
7013
7025
|
function dlpScan(args, cfg) {
|
|
7014
7026
|
if (!cfg)
|
|
7015
7027
|
return null;
|
|
@@ -7026,7 +7038,7 @@ function dlpScan(args, cfg) {
|
|
|
7026
7038
|
}
|
|
7027
7039
|
for (const c of Array.isArray(cfg.custom) ? cfg.custom : []) {
|
|
7028
7040
|
try {
|
|
7029
|
-
if (
|
|
7041
|
+
if (dlpGlobToRe(c.re).test(text))
|
|
7030
7042
|
return c.name || "custom pattern";
|
|
7031
7043
|
} catch {
|
|
7032
7044
|
}
|
package/hooks/guard.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import { createHash } from 'node:crypto';
|
|
|
31
31
|
// the installed hook self-updates when the cloud version is higher (see
|
|
32
32
|
// maybeSelfUpdate). This is what makes guard fixes propagate without a manual
|
|
33
33
|
// reinstall — the same trust model as the OPA WASM this hook already runs.
|
|
34
|
-
const HOOK_VERSION =
|
|
34
|
+
const HOOK_VERSION = 19;
|
|
35
35
|
|
|
36
36
|
// Safe file read with size limit (1MB max) to prevent DoS via large files
|
|
37
37
|
const MAX_FILE_READ = 1024 * 1024; // 1MB
|
|
@@ -665,6 +665,17 @@ const DLP_PATTERNS = [
|
|
|
665
665
|
{ name: 'secret assignment', re: /(api[_-]?key|secret|token|password|passwd|access[_-]?key)["']?\s*[:=]\s*["']?[A-Za-z0-9/+_.-]{12,}/i },
|
|
666
666
|
];
|
|
667
667
|
|
|
668
|
+
// Custom patterns are GLOBs: `*` = any run of non-whitespace, same wildcard
|
|
669
|
+
// mechanic as policy/ghost.
|
|
670
|
+
function dlpGlobToRe(glob) {
|
|
671
|
+
let re = '';
|
|
672
|
+
for (const ch of String(glob || '')) {
|
|
673
|
+
if (ch === '*') re += '[^\\s]*';
|
|
674
|
+
else if ('.+?^${}()|[]\\'.indexOf(ch) !== -1) re += '\\' + ch;
|
|
675
|
+
else re += ch;
|
|
676
|
+
}
|
|
677
|
+
return new RegExp(re);
|
|
678
|
+
}
|
|
668
679
|
// Scan args against the enabled built-in patterns + any user custom patterns.
|
|
669
680
|
// `cfg` = { patterns: string[], custom: {name,re}[] }.
|
|
670
681
|
function dlpScan(args, cfg) {
|
|
@@ -676,7 +687,7 @@ function dlpScan(args, cfg) {
|
|
|
676
687
|
if (allow.has(p.name) && p.re.test(text)) return p.name;
|
|
677
688
|
}
|
|
678
689
|
for (const c of Array.isArray(cfg.custom) ? cfg.custom : []) {
|
|
679
|
-
try { if (
|
|
690
|
+
try { if (dlpGlobToRe(c.re).test(text)) return c.name || 'custom pattern'; } catch { /* skip invalid */ }
|
|
680
691
|
}
|
|
681
692
|
return null;
|
|
682
693
|
}
|
package/hooks/shield.mjs
CHANGED
|
@@ -55,13 +55,23 @@ function loadCfg() {
|
|
|
55
55
|
return { patterns: DLP_PATTERNS.map((p) => p.name), custom: [] };
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// Custom patterns are GLOBs: `*` = any run of non-whitespace, same as policy/ghost.
|
|
59
|
+
function dlpGlobToRe(glob, flags) {
|
|
60
|
+
let re = '';
|
|
61
|
+
for (const ch of String(glob || '')) {
|
|
62
|
+
if (ch === '*') re += '[^\\s]*';
|
|
63
|
+
else if ('.+?^${}()|[]\\'.indexOf(ch) !== -1) re += '\\' + ch;
|
|
64
|
+
else re += ch;
|
|
65
|
+
}
|
|
66
|
+
return new RegExp(re, flags);
|
|
67
|
+
}
|
|
58
68
|
function redactString(s, cfg) {
|
|
59
69
|
if (!cfg || typeof s !== 'string' || !s) return s;
|
|
60
70
|
const allow = new Set(cfg.patterns);
|
|
61
71
|
let out = s;
|
|
62
72
|
for (const p of DLP_PATTERNS) if (allow.has(p.name)) out = out.replace(p.re, `[REDACTED: ${p.name}]`);
|
|
63
73
|
for (const c of cfg.custom) {
|
|
64
|
-
try { out = out.replace(
|
|
74
|
+
try { out = out.replace(dlpGlobToRe(c.re, 'g'), `[REDACTED: ${c.name || 'custom'}]`); } catch { /* skip */ }
|
|
65
75
|
}
|
|
66
76
|
return out;
|
|
67
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.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": {
|