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-->4539<!--/stat:tests--> tests** across <!--stat:testFiles-->152<!--/stat:testFiles--> modular test files
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muaddib-scanner",
3
- "version": "2.11.177",
3
+ "version": "2.11.178",
4
4
  "description": "Supply-chain threat detection & response for npm & PyPI/Python",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "target": "node_modules",
3
- "timestamp": "2026-07-22T22:32:17.558Z",
3
+ "timestamp": "2026-07-23T07:53:45.520Z",
4
4
  "threats": [
5
5
  {
6
6
  "type": "string_mutation_obfuscation",
@@ -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.177",
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": 4539
15
+ "tests": 4543
16
16
  }