@solongate/proxy 0.6.1 → 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.
- package/dist/index.js +31 -27
- package/dist/init.js +31 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -664,10 +664,7 @@ function installHooks() {
|
|
|
664
664
|
const auditPath = join(hooksDir, "audit.mjs");
|
|
665
665
|
writeFileSync2(auditPath, AUDIT_SCRIPT);
|
|
666
666
|
console.log(` Created ${auditPath}`);
|
|
667
|
-
const
|
|
668
|
-
mkdirSync(claudeDir, { recursive: true });
|
|
669
|
-
const settingsPath = join(claudeDir, "settings.json");
|
|
670
|
-
const settings = {
|
|
667
|
+
const hookSettings = {
|
|
671
668
|
hooks: {
|
|
672
669
|
PreToolUse: [
|
|
673
670
|
{
|
|
@@ -687,19 +684,28 @@ function installHooks() {
|
|
|
687
684
|
]
|
|
688
685
|
}
|
|
689
686
|
};
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
687
|
+
const clients = [
|
|
688
|
+
{ name: "Claude Code", dir: ".claude" },
|
|
689
|
+
{ name: "Cursor", dir: ".cursor" }
|
|
690
|
+
];
|
|
691
|
+
for (const client of clients) {
|
|
692
|
+
const clientDir = resolve2(client.dir);
|
|
693
|
+
mkdirSync(clientDir, { recursive: true });
|
|
694
|
+
const settingsPath = join(clientDir, "settings.json");
|
|
695
|
+
let existing = {};
|
|
696
|
+
try {
|
|
697
|
+
existing = JSON.parse(readFileSync3(settingsPath, "utf-8"));
|
|
698
|
+
} catch {
|
|
699
|
+
}
|
|
700
|
+
const merged = { ...existing, hooks: hookSettings.hooks };
|
|
701
|
+
writeFileSync2(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
702
|
+
console.log(` Created ${settingsPath}`);
|
|
694
703
|
}
|
|
695
|
-
const merged = { ...existing, hooks: settings.hooks };
|
|
696
|
-
writeFileSync2(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
697
|
-
console.log(` Created ${settingsPath}`);
|
|
698
704
|
console.log("");
|
|
699
705
|
console.log(" Hooks installed:");
|
|
700
706
|
console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
|
|
701
707
|
console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
|
|
702
|
-
console.log("
|
|
708
|
+
console.log(" Activated for: Claude Code, Cursor");
|
|
703
709
|
}
|
|
704
710
|
function ensureEnvFile() {
|
|
705
711
|
const envPath = resolve2(".env");
|
|
@@ -979,17 +985,13 @@ function matchGlob(str, pattern) {
|
|
|
979
985
|
|
|
980
986
|
// \u2500\u2500 Path Glob (supports **) \u2500\u2500
|
|
981
987
|
function matchPathGlob(path, pattern) {
|
|
982
|
-
const p = path.replace(
|
|
983
|
-
const g = pattern.replace(
|
|
988
|
+
const p = path.replace(/\\\\/g, '/').toLowerCase();
|
|
989
|
+
const g = pattern.replace(/\\\\/g, '/').toLowerCase();
|
|
984
990
|
if (p === g) return true;
|
|
985
991
|
if (g.includes('**')) {
|
|
986
|
-
const parts = g.split('**');
|
|
987
|
-
if (parts.length ===
|
|
988
|
-
|
|
989
|
-
const matchPre = !pre || p.startsWith(pre) || p.includes(pre);
|
|
990
|
-
const matchSuf = !suf || p.endsWith(suf) || p.includes(suf.slice(1));
|
|
991
|
-
return matchPre && matchSuf;
|
|
992
|
-
}
|
|
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));
|
|
993
995
|
}
|
|
994
996
|
return matchGlob(p, g);
|
|
995
997
|
}
|
|
@@ -1018,14 +1020,14 @@ function extractFilenames(args) {
|
|
|
1018
1020
|
for (const s of scanStrings(args)) {
|
|
1019
1021
|
if (/^https?:\\/\\//i.test(s)) continue;
|
|
1020
1022
|
if (s.includes('/') || s.includes('\\\\')) {
|
|
1021
|
-
const base = s.replace(
|
|
1023
|
+
const base = s.replace(/\\\\/g, '/').split('/').pop();
|
|
1022
1024
|
if (base) names.add(base);
|
|
1023
1025
|
continue;
|
|
1024
1026
|
}
|
|
1025
1027
|
if (s.includes(' ')) {
|
|
1026
1028
|
for (const tok of s.split(/\\s+/)) {
|
|
1027
1029
|
if (tok.includes('/') || tok.includes('\\\\')) {
|
|
1028
|
-
const b = tok.replace(
|
|
1030
|
+
const b = tok.replace(/\\\\/g, '/').split('/').pop();
|
|
1029
1031
|
if (b && looksLikeFilename(b)) names.add(b);
|
|
1030
1032
|
} else if (looksLikeFilename(tok)) names.add(tok);
|
|
1031
1033
|
}
|
|
@@ -1126,8 +1128,8 @@ process.stdin.on('end', async () => {
|
|
|
1126
1128
|
const args = data.tool_input || {};
|
|
1127
1129
|
|
|
1128
1130
|
// \u2500\u2500 Self-protection: block access to hook files and settings \u2500\u2500
|
|
1129
|
-
const allStrings = scanStrings(args).map(s => s.replace(
|
|
1130
|
-
const protectedPaths = ['.solongate', '.claude/settings.json', 'policy.json'];
|
|
1131
|
+
const allStrings = scanStrings(args).map(s => s.replace(/\\\\/g, '/').toLowerCase());
|
|
1132
|
+
const protectedPaths = ['.solongate', '.claude/settings.json', '.cursor/settings.json', 'policy.json'];
|
|
1131
1133
|
for (const s of allStrings) {
|
|
1132
1134
|
for (const p of protectedPaths) {
|
|
1133
1135
|
if (s.includes(p)) {
|
|
@@ -1138,10 +1140,12 @@ process.stdin.on('end', async () => {
|
|
|
1138
1140
|
}
|
|
1139
1141
|
}
|
|
1140
1142
|
|
|
1141
|
-
// Load policy
|
|
1143
|
+
// Load policy (use cwd from hook data if available)
|
|
1144
|
+
const hookCwd = data.cwd || process.cwd();
|
|
1142
1145
|
let policy;
|
|
1143
1146
|
try {
|
|
1144
|
-
|
|
1147
|
+
const policyPath = resolve(hookCwd, 'policy.json');
|
|
1148
|
+
policy = JSON.parse(readFileSync(policyPath, 'utf-8'));
|
|
1145
1149
|
} catch {
|
|
1146
1150
|
process.exit(0); // No policy = allow all
|
|
1147
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(
|
|
178
|
-
const g = pattern.replace(
|
|
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 ===
|
|
183
|
-
|
|
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(
|
|
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(
|
|
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,8 +317,8 @@ 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(
|
|
325
|
-
const protectedPaths = ['.solongate', '.claude/settings.json', 'policy.json'];
|
|
320
|
+
const allStrings = scanStrings(args).map(s => s.replace(/\\\\/g, '/').toLowerCase());
|
|
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) {
|
|
328
324
|
if (s.includes(p)) {
|
|
@@ -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
|
-
|
|
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
|
}
|
|
@@ -430,10 +428,7 @@ function installHooks() {
|
|
|
430
428
|
const auditPath = join(hooksDir, "audit.mjs");
|
|
431
429
|
writeFileSync(auditPath, AUDIT_SCRIPT);
|
|
432
430
|
console.log(` Created ${auditPath}`);
|
|
433
|
-
const
|
|
434
|
-
mkdirSync(claudeDir, { recursive: true });
|
|
435
|
-
const settingsPath = join(claudeDir, "settings.json");
|
|
436
|
-
const settings = {
|
|
431
|
+
const hookSettings = {
|
|
437
432
|
hooks: {
|
|
438
433
|
PreToolUse: [
|
|
439
434
|
{
|
|
@@ -453,19 +448,28 @@ function installHooks() {
|
|
|
453
448
|
]
|
|
454
449
|
}
|
|
455
450
|
};
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
451
|
+
const clients = [
|
|
452
|
+
{ name: "Claude Code", dir: ".claude" },
|
|
453
|
+
{ name: "Cursor", dir: ".cursor" }
|
|
454
|
+
];
|
|
455
|
+
for (const client of clients) {
|
|
456
|
+
const clientDir = resolve(client.dir);
|
|
457
|
+
mkdirSync(clientDir, { recursive: true });
|
|
458
|
+
const settingsPath = join(clientDir, "settings.json");
|
|
459
|
+
let existing = {};
|
|
460
|
+
try {
|
|
461
|
+
existing = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
const merged = { ...existing, hooks: hookSettings.hooks };
|
|
465
|
+
writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
466
|
+
console.log(` Created ${settingsPath}`);
|
|
460
467
|
}
|
|
461
|
-
const merged = { ...existing, hooks: settings.hooks };
|
|
462
|
-
writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
463
|
-
console.log(` Created ${settingsPath}`);
|
|
464
468
|
console.log("");
|
|
465
469
|
console.log(" Hooks installed:");
|
|
466
470
|
console.log(" guard.mjs \u2192 blocks policy-violating calls (pre-execution)");
|
|
467
471
|
console.log(" audit.mjs \u2192 logs all calls to dashboard (post-execution)");
|
|
468
|
-
console.log("
|
|
472
|
+
console.log(" Activated for: Claude Code, Cursor");
|
|
469
473
|
}
|
|
470
474
|
function ensureEnvFile() {
|
|
471
475
|
const envPath = resolve(".env");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.6.
|
|
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": {
|