muaddib-scanner 2.11.177 → 2.11.178
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/README.md
CHANGED
|
@@ -345,7 +345,7 @@ npm test
|
|
|
345
345
|
|
|
346
346
|
### Testing
|
|
347
347
|
|
|
348
|
-
- **<!--stat:tests-->
|
|
348
|
+
- **<!--stat:tests-->4543<!--/stat:tests--> tests** across <!--stat:testFiles-->152<!--/stat:testFiles--> modular test files
|
|
349
349
|
- **56 fuzz tests** - Malformed inputs, ReDoS, unicode, binary
|
|
350
350
|
- **Datadog 17K benchmark** - 14,587 confirmed malware samples (in-scope)
|
|
351
351
|
- **Ground truth validation** - 96 real-world attacks (95.74% TPR@3, 88.30% TPR@20 — v2.11.48 full measure on 94 in-scope)
|
package/package.json
CHANGED
package/src/scanner/dataflow.js
CHANGED
|
@@ -474,6 +474,29 @@ function analyzeFile(content, filePath, basePath) {
|
|
|
474
474
|
}
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
+
// Stream-based credential read: fs.createReadStream(<sensitive path>) is the
|
|
478
|
+
// stream equivalent of readFileSync. Registering it as a credential_read source
|
|
479
|
+
// closes the .pipe() exfil gap — createReadStream('/.ssh/id_rsa').pipe(net.connect(...))
|
|
480
|
+
// now scores the same as the readFileSync + socket.write form (the co-occurring
|
|
481
|
+
// network sink from the .pipe() argument — net.connect/http.request — is already
|
|
482
|
+
// detected by the MemberExpression sink handler below). Strictly gated on
|
|
483
|
+
// isCredentialPath: FP-measured 0/745 benign packages (createReadStream of a
|
|
484
|
+
// sensitive path is absent from legitimate code; the benign servers'
|
|
485
|
+
// createReadStream('public/index.html').pipe(res) is not sensitive-sourced, and
|
|
486
|
+
// the .pipe(res)/.pipe(createWriteStream) sinks are not network sinks). Deliberately
|
|
487
|
+
// NOT added to MODULE_SOURCE_METHODS to avoid the alias path, which does not
|
|
488
|
+
// re-check the path and would flag a non-sensitive aliased read.
|
|
489
|
+
if (callName === 'createReadStream' || callName === 'fs.createReadStream') {
|
|
490
|
+
const arg = node.arguments[0];
|
|
491
|
+
if (arg && isCredentialPath(arg, sensitivePathVars)) {
|
|
492
|
+
sources.push({
|
|
493
|
+
type: 'credential_read',
|
|
494
|
+
name: callName,
|
|
495
|
+
line: node.loc?.start?.line
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
477
500
|
// fs.promises.readFile(path) — 3-level member chain
|
|
478
501
|
if (node.callee.type === 'MemberExpression' &&
|
|
479
502
|
node.callee.object?.type === 'MemberExpression') {
|
package/stats.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "GENERATED by scripts/collect-stats.js — do not edit by hand. Run `npm run docs:stats`.",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.178",
|
|
4
4
|
"scanners": 22,
|
|
5
5
|
"rulesTotal": 277,
|
|
6
6
|
"rulesCore": 272,
|
|
@@ -12,5 +12,5 @@
|
|
|
12
12
|
"moduleGraph": 9,
|
|
13
13
|
"pythonAstDetectors": 6,
|
|
14
14
|
"testFiles": 152,
|
|
15
|
-
"tests":
|
|
15
|
+
"tests": 4543
|
|
16
16
|
}
|