@solongate/proxy 0.17.3 → 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/hooks/guard.mjs +32 -42
- package/package.json +1 -1
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": {
|