@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.
Files changed (2) hide show
  1. package/hooks/guard.mjs +32 -42
  2. 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: Dangerous execution pattern detection ──
456
- // These can construct ANY string at runtime block when touching protected dirs
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: node -e, python -c, perl -e, ruby -e
460
- // Extract the -e/-c argument and scan it
461
- const interpreterPatterns = [
462
- /\bnode\s+(?:-e|--eval)\s+["']([^"']+)["']/gi,
463
- /\bnode\s+(?:-e|--eval)\s+([^;&|"']+)/gi,
464
- /\bpython[23]?\s+-c\s+["']([^"']+)["']/gi,
465
- /\bperl\s+-e\s+["']([^"']+)["']/gi,
466
- /\bruby\s+-e\s+["']([^"']+)["']/gi,
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 interpreterPatterns) {
469
- for (const m of fullCmd.matchAll(pat)) {
470
- const code = m[1].toLowerCase();
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 piped to executionalways block
487
- if (/\bbase64\s+-d\b.*\|\s*(?:bash|sh|node|python|perl|ruby)\b/i.test(fullCmd) ||
488
- /\bbase64\s+--decode\b.*\|\s*(?:bash|sh|node|python|perl|ruby)\b/i.test(fullCmd)) {
489
- await blockSelfProtection('SOLONGATE: base64 decode piped to interpreter — blocked');
479
+ // 7b. Base64 decode in ANY contextblock 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: bash /path/file, sh /path/file
493
- // If "bash <file>" or "sh <file>" and the file is not a well-known script
494
- if (/\b(?:bash|sh)\s+(?:\/tmp\/|\/var\/tmp\/|~\/\.|\.\/[^.s])/i.test(fullCmd)) {
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. Process substitution and here-strings that could construct protected paths
499
- if (/>\s*\(\s*(?:rm|mv|cp|cat)\b/i.test(fullCmd) || /<<<.*(?:rm|mv|cp|cat)\b/i.test(fullCmd)) {
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
- const prefix = p.slice(0, 4); // e.g. ".sol", ".cla"
502
- if (fullCmd.includes(prefix)) {
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. xargs with destructive operations
509
- if (/\bxargs\b.*\b(?:rm|mv|cp|rmdir|unlink)\b/i.test(fullCmd)) {
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: xargs with destructive op near "' + p + '" — blocked');
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.17.3",
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": {