muaddib-scanner 2.2.26 → 2.2.27

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.
@@ -565,6 +565,7 @@ function handleCallExpression(node, ctx) {
565
565
 
566
566
  if (callName === 'eval') {
567
567
  ctx.hasEvalInFile = true;
568
+ ctx.hasDynamicExec = true;
568
569
  // Detect staged eval decode
569
570
  if (node.arguments.length === 1 && hasDecodeArg(node.arguments[0])) {
570
571
  ctx.threats.push({
@@ -585,6 +586,7 @@ function handleCallExpression(node, ctx) {
585
586
  });
586
587
  }
587
588
  } else if (callName === 'Function') {
589
+ ctx.hasDynamicExec = true;
588
590
  // Detect staged Function decode
589
591
  if (node.arguments.length >= 1 && hasDecodeArg(node.arguments[node.arguments.length - 1])) {
590
592
  ctx.threats.push({
@@ -679,12 +681,57 @@ function handleCallExpression(node, ctx) {
679
681
  });
680
682
  }
681
683
  if (propName === '_compile') {
684
+ ctx.hasDynamicExec = true;
682
685
  ctx.threats.push({
683
686
  type: 'module_compile',
684
687
  severity: 'CRITICAL',
685
688
  message: 'module._compile() detected — executes arbitrary code from string in module context (flatmap-stream pattern).',
686
689
  file: ctx.relFile
687
690
  });
691
+ // SANDWORM_MODE: Module._compile with non-literal argument = dynamic code execution
692
+ if (node.arguments.length >= 1 && !hasOnlyStringLiteralArgs(node)) {
693
+ ctx.threats.push({
694
+ type: 'module_compile_dynamic',
695
+ severity: 'CRITICAL',
696
+ message: 'In-memory code execution via Module._compile(). Common malware evasion technique.',
697
+ file: ctx.relFile
698
+ });
699
+ }
700
+ // Module._compile counts as temp file exec for write-execute-delete pattern
701
+ ctx.hasTempFileExec = ctx.hasTempFileExec || ctx.hasTmpdirInContent;
702
+ }
703
+
704
+ // SANDWORM_MODE: Track writeFileSync/writeFile to temp paths
705
+ if (propName === 'writeFileSync' || propName === 'writeFile') {
706
+ const arg = node.arguments && node.arguments[0];
707
+ if (arg) {
708
+ const strVal = extractStringValue(arg);
709
+ if (strVal && (/\/dev\/shm\b/.test(strVal) || /\btmp\b/i.test(strVal) || /\btemp\b/i.test(strVal))) {
710
+ ctx.hasTempFileWrite = true;
711
+ }
712
+ // Variable reference to tmpdir/temp path
713
+ if (!strVal && (arg.type === 'Identifier' || arg.type === 'CallExpression' || arg.type === 'MemberExpression')) {
714
+ // Dynamic path — check if file content involves tmpdir patterns
715
+ ctx.hasTempFileWrite = ctx.hasTempFileWrite || ctx.hasTmpdirInContent;
716
+ }
717
+ }
718
+ }
719
+
720
+ // SANDWORM_MODE: Track unlinkSync/rmSync (file deletion)
721
+ if (propName === 'unlinkSync' || propName === 'unlink' || propName === 'rmSync') {
722
+ ctx.hasFileDelete = true;
723
+ }
724
+ }
725
+
726
+ // SANDWORM_MODE: Track require() of temp path (execution of temp file)
727
+ if (callName === 'require' && node.arguments.length > 0) {
728
+ const arg = node.arguments[0];
729
+ const strVal = extractStringValue(arg);
730
+ if (strVal && (/\/dev\/shm\b/.test(strVal) || /\btmp\b/i.test(strVal) || /\btemp\b/i.test(strVal))) {
731
+ ctx.hasTempFileExec = true;
732
+ } else if (!strVal && ctx.hasTmpdirInContent) {
733
+ // Variable argument in a file that references tmpdir paths
734
+ ctx.hasTempFileExec = true;
688
735
  }
689
736
  }
690
737
  }
@@ -897,6 +944,26 @@ function handleMemberExpression(node, ctx) {
897
944
  }
898
945
 
899
946
  function handlePostWalk(ctx) {
947
+ // SANDWORM_MODE: zlib inflate + base64 decode + eval/Function/Module._compile = obfuscated payload
948
+ if (ctx.hasZlibInflate && ctx.hasBase64Decode && ctx.hasDynamicExec) {
949
+ ctx.threats.push({
950
+ type: 'zlib_inflate_eval',
951
+ severity: 'CRITICAL',
952
+ message: 'Obfuscated payload: zlib inflate + base64 decode + dynamic execution. No legitimate package uses this pattern.',
953
+ file: ctx.relFile
954
+ });
955
+ }
956
+
957
+ // SANDWORM_MODE: write + execute + delete = anti-forensics staging
958
+ if (ctx.hasTempFileWrite && ctx.hasTempFileExec && ctx.hasFileDelete) {
959
+ ctx.threats.push({
960
+ type: 'write_execute_delete',
961
+ severity: 'HIGH',
962
+ message: 'Anti-forensics: write, execute, then delete. Typical malware staging pattern.',
963
+ file: ctx.relFile
964
+ });
965
+ }
966
+
900
967
  // JS reverse shell pattern
901
968
  if (ctx.hasJsReverseShell) {
902
969
  ctx.threats.push({
@@ -75,7 +75,16 @@ function analyzeFile(content, filePath, basePath) {
75
75
  /\.pipe\b/.test(content) &&
76
76
  (/\bspawn\b/.test(content) || /\bstdin\b/.test(content) || /\bstdout\b/.test(content)),
77
77
  hasBinaryFileLiteral: /\.(png|jpg|jpeg|gif|bmp|ico|wasm)\b/i.test(content),
78
- hasEvalInFile: false
78
+ hasEvalInFile: false,
79
+ // SANDWORM_MODE: zlib inflate + base64 + eval co-occurrence
80
+ hasZlibInflate: /\brequire\s*\(\s*['"]zlib['"]\s*\)/.test(content) || /\bzlib\s*\.\s*inflate/.test(content),
81
+ hasBase64Decode: /Buffer\.from\s*\([^)]*,\s*['"]base64['"]/.test(content),
82
+ hasDynamicExec: false, // set in handleCallExpression for eval/Function/Module._compile
83
+ // SANDWORM_MODE: write + execute + delete anti-forensics
84
+ hasTempFileWrite: false,
85
+ hasTempFileExec: false,
86
+ hasFileDelete: false,
87
+ hasTmpdirInContent: /\btmpdir\b|\/dev\/shm\b|\/tmp\b/i.test(content)
79
88
  };
80
89
 
81
90
  walk.simple(ast, {