@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 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(new RegExp(c3.re, "g"), `[REDACTED: ${c3.name || "custom"}]`);
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(new RegExp(c.re, "g"), `[REDACTED: ${c.name || "custom"}]`);
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(new RegExp(c.re, 'g'), '[REDACTED:' + (c.name || 'custom') + ']'); } catch { /* skip invalid */ }
228
+ try { out = out.replace(dlpGlobToRe(c.re, 'g'), '[REDACTED:' + (c.name || 'custom') + ']'); } catch { /* skip invalid */ }
218
229
  }
219
230
  return out;
220
231
  }
@@ -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 = 18;
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 (new RegExp(c.re).test(text))
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 = 18;
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 (new RegExp(c.re).test(text)) return c.name || 'custom pattern'; } catch { /* skip invalid */ }
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(new RegExp(c.re, 'g'), `[REDACTED: ${c.name || 'custom'}]`); } catch { /* skip */ }
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.53.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": {