muaddib-scanner 2.11.32 → 2.11.33
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/package.json
CHANGED
package/src/rules/index.js
CHANGED
|
@@ -685,6 +685,19 @@ const RULES = {
|
|
|
685
685
|
references: ['https://attack.mitre.org/techniques/T1036/009/'],
|
|
686
686
|
mitre: 'T1036.009'
|
|
687
687
|
},
|
|
688
|
+
silent_stealth_process: {
|
|
689
|
+
id: 'MUADDIB-AST-092',
|
|
690
|
+
name: 'Silent Stealth Background Process',
|
|
691
|
+
severity: 'CRITICAL',
|
|
692
|
+
confidence: 'high',
|
|
693
|
+
description: 'spawn/fork avec {detached: true, stdio: \'ignore\'} — combinaison qui detache le processus ET silence tous ses I/O. Signal de stealth specifique aux payloads installes via lifecycle (Shai-Hulud) qui doivent survivre a npm install sans laisser de trace dans les logs.',
|
|
694
|
+
references: [
|
|
695
|
+
'https://github.com/DataDog/guarddog/blob/main/guarddog/analyzer/sourcecode/npm-silent-process-execution.yml',
|
|
696
|
+
'https://attack.mitre.org/techniques/T1036/009/',
|
|
697
|
+
'https://attack.mitre.org/techniques/T1564/'
|
|
698
|
+
],
|
|
699
|
+
mitre: 'T1564'
|
|
700
|
+
},
|
|
688
701
|
dangerous_call_function: {
|
|
689
702
|
id: 'MUADDIB-AST-005',
|
|
690
703
|
name: 'new Function() Constructor',
|
|
@@ -491,6 +491,31 @@ function handleCallExpression(node, ctx) {
|
|
|
491
491
|
message: `${callName}() with {detached: true} — background process survives parent exit (evasion technique).`,
|
|
492
492
|
file: ctx.relFile
|
|
493
493
|
});
|
|
494
|
+
// F6 — silent_stealth_process: detached + stdio:'ignore' = full I/O
|
|
495
|
+
// silence. Combo is a stronger stealth indicator (Shai-Hulud pattern).
|
|
496
|
+
// Emitted ADDITIONALLY (not replacing) so existing compounds that
|
|
497
|
+
// depend on detached_process (detached_credential_exfil, binary_dropper)
|
|
498
|
+
// continue to fire. Inspired by GuardDog's npm-silent-process-execution.yml.
|
|
499
|
+
const hasStdioIgnore = lastArg.properties.some(p => {
|
|
500
|
+
if (p.key?.type !== 'Identifier' || p.key.name !== 'stdio') return false;
|
|
501
|
+
// stdio: 'ignore'
|
|
502
|
+
if (p.value?.type === 'Literal' && p.value.value === 'ignore') return true;
|
|
503
|
+
// stdio: ['ignore', 'ignore', 'ignore'] — array form, all elements 'ignore'
|
|
504
|
+
if (p.value?.type === 'ArrayExpression' && p.value.elements.length > 0) {
|
|
505
|
+
return p.value.elements.every(el =>
|
|
506
|
+
el?.type === 'Literal' && el.value === 'ignore'
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
return false;
|
|
510
|
+
});
|
|
511
|
+
if (hasStdioIgnore) {
|
|
512
|
+
ctx.threats.push({
|
|
513
|
+
type: 'silent_stealth_process',
|
|
514
|
+
severity: 'CRITICAL',
|
|
515
|
+
message: `${callName}() with {detached: true, stdio: 'ignore'} — fully detached silent background process (stealth payload pattern).`,
|
|
516
|
+
file: ctx.relFile
|
|
517
|
+
});
|
|
518
|
+
}
|
|
494
519
|
}
|
|
495
520
|
}
|
|
496
521
|
}
|