@solongate/proxy 0.17.2 → 0.18.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 +16 -5
- package/dist/init.js +16 -5
- package/hooks/guard.mjs +32 -42
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -469,9 +469,14 @@ function unlockProtectedDirs() {
|
|
|
469
469
|
if (!existsSync3(fullDir)) continue;
|
|
470
470
|
try {
|
|
471
471
|
if (process.platform === "win32") {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
472
|
+
try {
|
|
473
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /remove:d '*S-1-1-0' /T /Q"`, { stdio: "ignore" });
|
|
474
|
+
} catch {
|
|
475
|
+
}
|
|
476
|
+
try {
|
|
477
|
+
execSync(`attrib -R /S /D "${fullDir}"`, { stdio: "ignore" });
|
|
478
|
+
} catch {
|
|
479
|
+
}
|
|
475
480
|
} else {
|
|
476
481
|
try {
|
|
477
482
|
execSync(`chattr -i -R "${fullDir}"`, { stdio: "ignore" });
|
|
@@ -544,8 +549,14 @@ function installHooks(selectedTools = []) {
|
|
|
544
549
|
const fullDir = resolve2(dir);
|
|
545
550
|
if (existsSync3(fullDir)) {
|
|
546
551
|
try {
|
|
547
|
-
|
|
548
|
-
|
|
552
|
+
try {
|
|
553
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /remove:d '*S-1-1-0' /T /Q"`, { stdio: "ignore" });
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
try {
|
|
557
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /deny '*S-1-1-0:(OI)(CI)(DE,DC,WD,AD,WA)' /T /Q"`, { stdio: "ignore" });
|
|
558
|
+
} catch {
|
|
559
|
+
}
|
|
549
560
|
execSync(`attrib +R /S /D "${fullDir}"`, { stdio: "ignore" });
|
|
550
561
|
} catch {
|
|
551
562
|
}
|
package/dist/init.js
CHANGED
|
@@ -176,9 +176,14 @@ function unlockProtectedDirs() {
|
|
|
176
176
|
if (!existsSync(fullDir)) continue;
|
|
177
177
|
try {
|
|
178
178
|
if (process.platform === "win32") {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
try {
|
|
180
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /remove:d '*S-1-1-0' /T /Q"`, { stdio: "ignore" });
|
|
181
|
+
} catch {
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
execSync(`attrib -R /S /D "${fullDir}"`, { stdio: "ignore" });
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
182
187
|
} else {
|
|
183
188
|
try {
|
|
184
189
|
execSync(`chattr -i -R "${fullDir}"`, { stdio: "ignore" });
|
|
@@ -251,8 +256,14 @@ function installHooks(selectedTools = []) {
|
|
|
251
256
|
const fullDir = resolve(dir);
|
|
252
257
|
if (existsSync(fullDir)) {
|
|
253
258
|
try {
|
|
254
|
-
|
|
255
|
-
|
|
259
|
+
try {
|
|
260
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /remove:d '*S-1-1-0' /T /Q"`, { stdio: "ignore" });
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
execSync(`powershell.exe -Command "icacls '${fullDir}' /deny '*S-1-1-0:(OI)(CI)(DE,DC,WD,AD,WA)' /T /Q"`, { stdio: "ignore" });
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
256
267
|
execSync(`attrib +R /S /D "${fullDir}"`, { stdio: "ignore" });
|
|
257
268
|
} catch {
|
|
258
269
|
}
|
package/hooks/guard.mjs
CHANGED
|
@@ -452,64 +452,54 @@ process.stdin.on('end', async () => {
|
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
-
// ── Layer 7:
|
|
456
|
-
//
|
|
455
|
+
// ── Layer 7: Block ALL inline code execution & dangerous patterns ──
|
|
456
|
+
// Runtime string construction (atob, Buffer.from, fromCharCode, array.join)
|
|
457
|
+
// makes static analysis impossible. Blanket-block these patterns.
|
|
457
458
|
const fullCmd = rawStrings.join(' ');
|
|
458
459
|
|
|
459
|
-
// 7a. Inline interpreter execution
|
|
460
|
-
//
|
|
461
|
-
const
|
|
462
|
-
/\bnode\s+(?:-e|--eval)\
|
|
463
|
-
/\bnode\s
|
|
464
|
-
/\bpython[23]?\s+-c\
|
|
465
|
-
/\bperl\s+-e\
|
|
466
|
-
/\bruby\s+-e\
|
|
460
|
+
// 7a. Inline interpreter execution — TOTAL BLOCK (no content scan needed)
|
|
461
|
+
// These can construct ANY string at runtime, bypassing all static analysis
|
|
462
|
+
const blockedInterpreters = [
|
|
463
|
+
[/\bnode\s+(?:-e|--eval)\b/i, 'node -e/--eval'],
|
|
464
|
+
[/\bnode\s+-p\b/i, 'node -p'],
|
|
465
|
+
[/\bpython[23]?\s+-c\b/i, 'python -c'],
|
|
466
|
+
[/\bperl\s+-e\b/i, 'perl -e'],
|
|
467
|
+
[/\bruby\s+-e\b/i, 'ruby -e'],
|
|
468
|
+
[/\bpowershell(?:\.exe)?\s+.*-(?:EncodedCommand|e|ec)\b/i, 'powershell -EncodedCommand'],
|
|
469
|
+
[/\bpwsh(?:\.exe)?\s+.*-(?:EncodedCommand|e|ec)\b/i, 'pwsh -EncodedCommand'],
|
|
470
|
+
[/\bpowershell(?:\.exe)?\s+-c(?:ommand)?\b/i, 'powershell -Command'],
|
|
471
|
+
[/\bpwsh(?:\.exe)?\s+-c(?:ommand)?\b/i, 'pwsh -Command'],
|
|
467
472
|
];
|
|
468
|
-
for (const pat of
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
for (const p of protectedPaths) {
|
|
472
|
-
if (code.includes(p)) {
|
|
473
|
-
await blockSelfProtection('SOLONGATE: Interpreter code targets "' + p + '" — blocked');
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
// Also check the normalized version
|
|
477
|
-
const normCode = normalizeShell(code);
|
|
478
|
-
for (const p of protectedPaths) {
|
|
479
|
-
if (normCode.includes(p)) {
|
|
480
|
-
await blockSelfProtection('SOLONGATE: Interpreter code targets "' + p + '" — blocked');
|
|
481
|
-
}
|
|
482
|
-
}
|
|
473
|
+
for (const [pat, name] of blockedInterpreters) {
|
|
474
|
+
if (pat.test(fullCmd)) {
|
|
475
|
+
await blockSelfProtection('SOLONGATE: Inline code execution blocked (' + name + ')');
|
|
483
476
|
}
|
|
484
477
|
}
|
|
485
478
|
|
|
486
|
-
// 7b. Base64 decode
|
|
487
|
-
if (/\bbase64\s
|
|
488
|
-
|
|
489
|
-
await blockSelfProtection('SOLONGATE: base64 decode piped to interpreter — blocked');
|
|
479
|
+
// 7b. Base64 decode in ANY context — block when piped to anything
|
|
480
|
+
if (/\bbase64\s+(?:-d|--decode)\b/i.test(fullCmd) && /\|/i.test(fullCmd)) {
|
|
481
|
+
await blockSelfProtection('SOLONGATE: base64 decode in pipe chain — blocked');
|
|
490
482
|
}
|
|
491
483
|
|
|
492
|
-
// 7c. Temp script file execution
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
await blockSelfProtection('SOLONGATE: Temp script execution detected — blocked');
|
|
484
|
+
// 7c. Temp/arbitrary script file execution
|
|
485
|
+
if (/\b(?:bash|sh)\s+(?:\/tmp\/|\/var\/tmp\/|~\/|\/dev\/)/i.test(fullCmd)) {
|
|
486
|
+
await blockSelfProtection('SOLONGATE: Script execution from temp path — blocked');
|
|
496
487
|
}
|
|
497
488
|
|
|
498
|
-
// 7d.
|
|
499
|
-
if (
|
|
489
|
+
// 7d. xargs with destructive operations
|
|
490
|
+
if (/\bxargs\b.*\b(?:rm|mv|cp|rmdir|unlink|del)\b/i.test(fullCmd)) {
|
|
500
491
|
for (const p of protectedPaths) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
await blockSelfProtection('SOLONGATE: Process substitution near protected path "' + p + '" — blocked');
|
|
492
|
+
if (fullCmd.includes(p.slice(0, 4))) {
|
|
493
|
+
await blockSelfProtection('SOLONGATE: xargs with destructive op near "' + p + '" — blocked');
|
|
504
494
|
}
|
|
505
495
|
}
|
|
506
496
|
}
|
|
507
497
|
|
|
508
|
-
// 7e.
|
|
509
|
-
if (/\
|
|
498
|
+
// 7e. cmd.exe /c with encoded/constructed commands
|
|
499
|
+
if (/\bcmd(?:\.exe)?\s+\/c\b/i.test(fullCmd)) {
|
|
510
500
|
for (const p of protectedPaths) {
|
|
511
|
-
if (fullCmd.includes(p.slice(0, 4))) {
|
|
512
|
-
await blockSelfProtection('SOLONGATE:
|
|
501
|
+
if (fullCmd.includes(p) || fullCmd.includes(p.slice(0, 4))) {
|
|
502
|
+
await blockSelfProtection('SOLONGATE: cmd.exe /c near protected path — blocked');
|
|
513
503
|
}
|
|
514
504
|
}
|
|
515
505
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
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": {
|