@solongate/proxy 0.20.0 → 0.21.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 +29 -1
- package/package.json +1 -1
package/hooks/guard.mjs
CHANGED
|
@@ -562,6 +562,33 @@ process.stdin.on('end', async () => {
|
|
|
562
562
|
await blockSelfProtection('SOLONGATE: Heredoc to interpreter — blocked');
|
|
563
563
|
}
|
|
564
564
|
|
|
565
|
+
// 7-pre3. Command substitution + destructive = BLOCK
|
|
566
|
+
// Catches: rm -rf $(node scan.mjs), rm `node scan.mjs`, rm $(bash scan.sh)
|
|
567
|
+
// Pattern: destructive command + $() or `` containing interpreter call
|
|
568
|
+
const hasDestructive = /\b(?:rm|rmdir|del|unlink|mv|move|rename|shred)\b/i.test(fullCmd);
|
|
569
|
+
const hasCmdSubInterpreter = /\$\(\s*(?:node|bash|sh|python[23]?|perl|ruby)\b/i.test(fullCmd)
|
|
570
|
+
|| /`\s*(?:node|bash|sh|python[23]?|perl|ruby)\b/i.test(fullCmd);
|
|
571
|
+
if (hasDestructive && hasCmdSubInterpreter) {
|
|
572
|
+
await blockSelfProtection('SOLONGATE: Command substitution + destructive op — blocked');
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// 7-pre4. Pipe from interpreter to destructive loop = BLOCK
|
|
576
|
+
// Catches: node scan.mjs | while read d; do rm -rf "$d"; done
|
|
577
|
+
// node scan.mjs | xargs rm -rf
|
|
578
|
+
// bash scan.sh | while read ...
|
|
579
|
+
const pipeFromInterpreter = /\b(?:node|bash|sh|python[23]?|perl|ruby)\s+\S+\s*\|/i;
|
|
580
|
+
if (pipeFromInterpreter.test(fullCmd) && hasDestructive) {
|
|
581
|
+
await blockSelfProtection('SOLONGATE: Pipe from script to destructive command — blocked');
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// 7-pre5. Script chaining: interpreter + destructive in same command chain
|
|
585
|
+
// Catches: node scan.mjs && rm -rf $(cat /tmp/targets.txt)
|
|
586
|
+
// bash scan.sh; while read d < targets.txt; do rm -rf "$d"; done
|
|
587
|
+
const hasScriptExec = /\b(?:node|bash|sh|python[23]?|perl|ruby)\s+\S+\.\S+/i.test(fullCmd);
|
|
588
|
+
if (hasScriptExec && hasDestructive) {
|
|
589
|
+
await blockSelfProtection('SOLONGATE: Script execution + destructive command in chain — blocked');
|
|
590
|
+
}
|
|
591
|
+
|
|
565
592
|
// 7a. Inline interpreter execution — TOTAL BLOCK (no content scan needed)
|
|
566
593
|
// These can construct ANY string at runtime, bypassing all static analysis
|
|
567
594
|
const blockedInterpreters = [
|
|
@@ -583,7 +610,8 @@ process.stdin.on('end', async () => {
|
|
|
583
610
|
|
|
584
611
|
// 7b. Pipe-to-interpreter — TOTAL BLOCK
|
|
585
612
|
// Any content piped to an interpreter can construct arbitrary commands at runtime
|
|
586
|
-
|
|
613
|
+
// Also catches: | xargs node, | xargs bash, etc.
|
|
614
|
+
const pipeToInterpreter = /\|\s*(?:xargs\s+)?(?:node|bash|sh|python[23]?|perl|ruby|php)\b/i;
|
|
587
615
|
if (pipeToInterpreter.test(fullCmd)) {
|
|
588
616
|
await blockSelfProtection('SOLONGATE: Pipe to interpreter blocked — runtime bypass risk');
|
|
589
617
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.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": {
|