@solongate/proxy 0.6.2 → 0.6.3

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 (3) hide show
  1. package/dist/index.js +12 -14
  2. package/dist/init.js +12 -14
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -985,17 +985,13 @@ function matchGlob(str, pattern) {
985
985
 
986
986
  // \u2500\u2500 Path Glob (supports **) \u2500\u2500
987
987
  function matchPathGlob(path, pattern) {
988
- const p = path.replace(/\\\\\\\\/g, '/').toLowerCase();
989
- const g = pattern.replace(/\\\\\\\\/g, '/').toLowerCase();
988
+ const p = path.replace(/\\\\/g, '/').toLowerCase();
989
+ const g = pattern.replace(/\\\\/g, '/').toLowerCase();
990
990
  if (p === g) return true;
991
991
  if (g.includes('**')) {
992
- const parts = g.split('**');
993
- if (parts.length === 2) {
994
- const [pre, suf] = parts;
995
- const matchPre = !pre || p.startsWith(pre) || p.includes(pre);
996
- const matchSuf = !suf || p.endsWith(suf) || p.includes(suf.slice(1));
997
- return matchPre && matchSuf;
998
- }
992
+ const parts = g.split('**').filter(s => s.length > 0);
993
+ if (parts.length === 0) return true; // just ** or ****
994
+ return parts.every(segment => p.includes(segment));
999
995
  }
1000
996
  return matchGlob(p, g);
1001
997
  }
@@ -1024,14 +1020,14 @@ function extractFilenames(args) {
1024
1020
  for (const s of scanStrings(args)) {
1025
1021
  if (/^https?:\\/\\//i.test(s)) continue;
1026
1022
  if (s.includes('/') || s.includes('\\\\')) {
1027
- const base = s.replace(/\\\\\\\\/g, '/').split('/').pop();
1023
+ const base = s.replace(/\\\\/g, '/').split('/').pop();
1028
1024
  if (base) names.add(base);
1029
1025
  continue;
1030
1026
  }
1031
1027
  if (s.includes(' ')) {
1032
1028
  for (const tok of s.split(/\\s+/)) {
1033
1029
  if (tok.includes('/') || tok.includes('\\\\')) {
1034
- const b = tok.replace(/\\\\\\\\/g, '/').split('/').pop();
1030
+ const b = tok.replace(/\\\\/g, '/').split('/').pop();
1035
1031
  if (b && looksLikeFilename(b)) names.add(b);
1036
1032
  } else if (looksLikeFilename(tok)) names.add(tok);
1037
1033
  }
@@ -1132,7 +1128,7 @@ process.stdin.on('end', async () => {
1132
1128
  const args = data.tool_input || {};
1133
1129
 
1134
1130
  // \u2500\u2500 Self-protection: block access to hook files and settings \u2500\u2500
1135
- const allStrings = scanStrings(args).map(s => s.replace(/\\\\\\\\/g, '/').toLowerCase());
1131
+ const allStrings = scanStrings(args).map(s => s.replace(/\\\\/g, '/').toLowerCase());
1136
1132
  const protectedPaths = ['.solongate', '.claude/settings.json', '.cursor/settings.json', 'policy.json'];
1137
1133
  for (const s of allStrings) {
1138
1134
  for (const p of protectedPaths) {
@@ -1144,10 +1140,12 @@ process.stdin.on('end', async () => {
1144
1140
  }
1145
1141
  }
1146
1142
 
1147
- // Load policy
1143
+ // Load policy (use cwd from hook data if available)
1144
+ const hookCwd = data.cwd || process.cwd();
1148
1145
  let policy;
1149
1146
  try {
1150
- policy = JSON.parse(readFileSync(resolve('policy.json'), 'utf-8'));
1147
+ const policyPath = resolve(hookCwd, 'policy.json');
1148
+ policy = JSON.parse(readFileSync(policyPath, 'utf-8'));
1151
1149
  } catch {
1152
1150
  process.exit(0); // No policy = allow all
1153
1151
  }
package/dist/init.js CHANGED
@@ -174,17 +174,13 @@ function matchGlob(str, pattern) {
174
174
 
175
175
  // \u2500\u2500 Path Glob (supports **) \u2500\u2500
176
176
  function matchPathGlob(path, pattern) {
177
- const p = path.replace(/\\\\\\\\/g, '/').toLowerCase();
178
- const g = pattern.replace(/\\\\\\\\/g, '/').toLowerCase();
177
+ const p = path.replace(/\\\\/g, '/').toLowerCase();
178
+ const g = pattern.replace(/\\\\/g, '/').toLowerCase();
179
179
  if (p === g) return true;
180
180
  if (g.includes('**')) {
181
- const parts = g.split('**');
182
- if (parts.length === 2) {
183
- const [pre, suf] = parts;
184
- const matchPre = !pre || p.startsWith(pre) || p.includes(pre);
185
- const matchSuf = !suf || p.endsWith(suf) || p.includes(suf.slice(1));
186
- return matchPre && matchSuf;
187
- }
181
+ const parts = g.split('**').filter(s => s.length > 0);
182
+ if (parts.length === 0) return true; // just ** or ****
183
+ return parts.every(segment => p.includes(segment));
188
184
  }
189
185
  return matchGlob(p, g);
190
186
  }
@@ -213,14 +209,14 @@ function extractFilenames(args) {
213
209
  for (const s of scanStrings(args)) {
214
210
  if (/^https?:\\/\\//i.test(s)) continue;
215
211
  if (s.includes('/') || s.includes('\\\\')) {
216
- const base = s.replace(/\\\\\\\\/g, '/').split('/').pop();
212
+ const base = s.replace(/\\\\/g, '/').split('/').pop();
217
213
  if (base) names.add(base);
218
214
  continue;
219
215
  }
220
216
  if (s.includes(' ')) {
221
217
  for (const tok of s.split(/\\s+/)) {
222
218
  if (tok.includes('/') || tok.includes('\\\\')) {
223
- const b = tok.replace(/\\\\\\\\/g, '/').split('/').pop();
219
+ const b = tok.replace(/\\\\/g, '/').split('/').pop();
224
220
  if (b && looksLikeFilename(b)) names.add(b);
225
221
  } else if (looksLikeFilename(tok)) names.add(tok);
226
222
  }
@@ -321,7 +317,7 @@ process.stdin.on('end', async () => {
321
317
  const args = data.tool_input || {};
322
318
 
323
319
  // \u2500\u2500 Self-protection: block access to hook files and settings \u2500\u2500
324
- const allStrings = scanStrings(args).map(s => s.replace(/\\\\\\\\/g, '/').toLowerCase());
320
+ const allStrings = scanStrings(args).map(s => s.replace(/\\\\/g, '/').toLowerCase());
325
321
  const protectedPaths = ['.solongate', '.claude/settings.json', '.cursor/settings.json', 'policy.json'];
326
322
  for (const s of allStrings) {
327
323
  for (const p of protectedPaths) {
@@ -333,10 +329,12 @@ process.stdin.on('end', async () => {
333
329
  }
334
330
  }
335
331
 
336
- // Load policy
332
+ // Load policy (use cwd from hook data if available)
333
+ const hookCwd = data.cwd || process.cwd();
337
334
  let policy;
338
335
  try {
339
- policy = JSON.parse(readFileSync(resolve('policy.json'), 'utf-8'));
336
+ const policyPath = resolve(hookCwd, 'policy.json');
337
+ policy = JSON.parse(readFileSync(policyPath, 'utf-8'));
340
338
  } catch {
341
339
  process.exit(0); // No policy = allow all
342
340
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "MCP security proxy — protect any MCP server with customizable policies, path/command constraints, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {