muaddib-scanner 2.11.113 → 2.11.114
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"target": "node_modules",
|
|
3
|
-
"timestamp": "2026-06-
|
|
3
|
+
"timestamp": "2026-06-14T12:30:49.542Z",
|
|
4
4
|
"threats": [
|
|
5
5
|
{
|
|
6
6
|
"type": "string_mutation_obfuscation",
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
},
|
|
245
245
|
{
|
|
246
246
|
"type": "credential_regex_harvest",
|
|
247
|
-
"severity": "
|
|
247
|
+
"severity": "LOW",
|
|
248
248
|
"message": "Credential regex patterns (token/password/secret/Bearer) + network call in same file — stream data credential harvesting.",
|
|
249
249
|
"file": "web-tree-sitter/web-tree-sitter.cjs",
|
|
250
250
|
"count": 1,
|
|
@@ -252,6 +252,11 @@
|
|
|
252
252
|
{
|
|
253
253
|
"rule": "count_threshold_floor",
|
|
254
254
|
"note": "retained one instance at original severity"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"rule": "sink_coupling",
|
|
258
|
+
"from": "HIGH",
|
|
259
|
+
"to": "LOW"
|
|
255
260
|
}
|
|
256
261
|
],
|
|
257
262
|
"originalSeverity": "HIGH",
|
|
@@ -266,7 +271,7 @@
|
|
|
266
271
|
],
|
|
267
272
|
"mitre": "T1552",
|
|
268
273
|
"playbook": "Code contient des regex de detection de credentials (Bearer, password, token, API key) combine avec un appel reseau. Technique de harvesting: scanne les donnees en transit (streams HTTP, fichiers) pour extraire des secrets et les exfiltrer. Supprimer le package. Auditer le trafic reseau sortant.",
|
|
269
|
-
"points":
|
|
274
|
+
"points": 1
|
|
270
275
|
},
|
|
271
276
|
{
|
|
272
277
|
"type": "proxy_data_intercept",
|
|
@@ -1823,18 +1828,18 @@
|
|
|
1823
1828
|
"summary": {
|
|
1824
1829
|
"total": 80,
|
|
1825
1830
|
"critical": 7,
|
|
1826
|
-
"high":
|
|
1831
|
+
"high": 10,
|
|
1827
1832
|
"medium": 32,
|
|
1828
|
-
"low":
|
|
1833
|
+
"low": 31,
|
|
1829
1834
|
"riskScore": 35,
|
|
1830
1835
|
"riskLevel": "MEDIUM",
|
|
1831
1836
|
"globalRiskScore": 100,
|
|
1832
|
-
"maxFileScore":
|
|
1837
|
+
"maxFileScore": 42,
|
|
1833
1838
|
"packageScore": 1,
|
|
1834
1839
|
"mostSuspiciousFile": "web-tree-sitter/web-tree-sitter.cjs",
|
|
1835
1840
|
"fileScores": {
|
|
1836
1841
|
"esquery/parser.js": 5,
|
|
1837
|
-
"web-tree-sitter/web-tree-sitter.cjs":
|
|
1842
|
+
"web-tree-sitter/web-tree-sitter.cjs": 42,
|
|
1838
1843
|
"web-tree-sitter/web-tree-sitter.js": 42,
|
|
1839
1844
|
"ajv/lib/ajv.js": 25,
|
|
1840
1845
|
"ajv/scripts/bundle.js": 10,
|
|
@@ -1927,12 +1932,6 @@
|
|
|
1927
1932
|
"points": 10,
|
|
1928
1933
|
"reason": "Binary file reference (.png/.jpg/.wasm/etc.) + eval() in same file — possible steganographic payload execution."
|
|
1929
1934
|
},
|
|
1930
|
-
{
|
|
1931
|
-
"rule": "MUADDIB-AST-041",
|
|
1932
|
-
"type": "credential_regex_harvest",
|
|
1933
|
-
"points": 10,
|
|
1934
|
-
"reason": "Credential regex patterns (token/password/secret/Bearer) + network call in same file — stream data credential harvesting."
|
|
1935
|
-
},
|
|
1936
1935
|
{
|
|
1937
1936
|
"rule": "MUADDIB-AST-020",
|
|
1938
1937
|
"type": "staged_binary_payload",
|
|
@@ -2185,6 +2184,12 @@
|
|
|
2185
2184
|
"points": 1,
|
|
2186
2185
|
"reason": "Dangerous call \"eval\" with dynamic expression detected."
|
|
2187
2186
|
},
|
|
2187
|
+
{
|
|
2188
|
+
"rule": "MUADDIB-AST-041",
|
|
2189
|
+
"type": "credential_regex_harvest",
|
|
2190
|
+
"points": 1,
|
|
2191
|
+
"reason": "Credential regex patterns (token/password/secret/Bearer) + network call in same file — stream data credential harvesting."
|
|
2192
|
+
},
|
|
2188
2193
|
{
|
|
2189
2194
|
"rule": "MUADDIB-AST-043",
|
|
2190
2195
|
"type": "proxy_data_intercept",
|
package/src/scoring.js
CHANGED
|
@@ -1029,6 +1029,28 @@ const FRAMEWORK_PROTO_RE = new RegExp(
|
|
|
1029
1029
|
'^(' + FRAMEWORK_PROTOTYPES.join('|') + ')\\.prototype\\.'
|
|
1030
1030
|
);
|
|
1031
1031
|
|
|
1032
|
+
// FPR sink-coupling (chantier 2026-06): independent exfil / remote-exec sink signals pointing at
|
|
1033
|
+
// an ANOMALOUS destination. A credential_regex_harvest signal is only a true positive when one of
|
|
1034
|
+
// these co-occurs in the package. Deliberately EXCLUDES benign network capability — a bare
|
|
1035
|
+
// fetch/http.get, remote_code_load to a first-party CDN/model host, a local server, or a native
|
|
1036
|
+
// build are NOT sinks. Dataflow-PROVEN harvest signals (intent_credential_exfil, cross_file_dataflow)
|
|
1037
|
+
// are included so a genuine read→exfil taint keeps the signal HIGH regardless of host reputation
|
|
1038
|
+
// (anti-FN floor). See _hasExfilSink + the credential_regex_harvest gate in applyFPReductions.
|
|
1039
|
+
const EXFIL_SINK_TYPES = new Set([
|
|
1040
|
+
'suspicious_domain', 'direct_ip_exfil', 'ioc_string_match', 'ioc_match',
|
|
1041
|
+
'known_malicious_package', 'pypi_malicious_package', 'shai_hulud_marker',
|
|
1042
|
+
'detached_credential_exfil', 'silent_stealth_process',
|
|
1043
|
+
'curl_pipe_shell', 'curl_env_exfil', 'reverse_shell', 'dns_exfil', 'oast_callback',
|
|
1044
|
+
'function_constructor_require', 'staged_remote_loader', 'staged_eval_decode',
|
|
1045
|
+
'fetch_decrypt_exec', 'download_exec_binary', 'self_destruct_eval',
|
|
1046
|
+
'newsletter_auto_follow', 'cross_file_dataflow', 'intent_credential_exfil',
|
|
1047
|
+
'intent_command_exfil', 'sandbox_known_exfil_domain', 'sandbox_network_after_sensitive_read'
|
|
1048
|
+
]);
|
|
1049
|
+
function _hasExfilSink(threats) {
|
|
1050
|
+
if (!Array.isArray(threats)) return false;
|
|
1051
|
+
return threats.some(t => EXFIL_SINK_TYPES.has(t.type) && t.severity !== 'LOW');
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1032
1054
|
function applyFPReductions(threats, reachableFiles, packageName, packageDeps, reachableFunctions) {
|
|
1033
1055
|
// Initialize reductions audit trail on each threat
|
|
1034
1056
|
// Store original severity before any FP reductions, so compound
|
|
@@ -1174,6 +1196,25 @@ function applyFPReductions(threats, reachableFiles, packageName, packageDeps, re
|
|
|
1174
1196
|
}
|
|
1175
1197
|
}
|
|
1176
1198
|
|
|
1199
|
+
// FPR sink-coupling gate (chantier 2026-06 — FPR-baseline-2026-06-14.md). credential_regex_harvest
|
|
1200
|
+
// is a weak signal alone: a credential-shaped regex co-located with a network call, with NO proof
|
|
1201
|
+
// the matched secret flows out and NO host-reputation check (ast.js:hasCredentialInsideRegex +
|
|
1202
|
+
// hasNetworkCallInFile). The blind FPR baseline measured 94.4% FP on it — it fires on nodemailer
|
|
1203
|
+
// SMTP code, redaction utilities in framework bundles, and SDKs that parse Authorization headers.
|
|
1204
|
+
// It is a real harvester ONLY when an independent exfil sink to an anomalous destination co-occurs
|
|
1205
|
+
// (suspicious_domain / direct_ip / ioc / detached-exfil / staged loader / curl exfil / dataflow-proven
|
|
1206
|
+
// taint ...). When no such sink is present, downgrade HIGH/CRITICAL → LOW. Runs after the dilution
|
|
1207
|
+
// floor so the floor's restored instance is also gated (the floor protects real exfil; with no sink
|
|
1208
|
+
// there is nothing to protect). No GT sample relies on credential_regex_harvest (verified).
|
|
1209
|
+
if (!_hasExfilSink(threats)) {
|
|
1210
|
+
for (const t of threats) {
|
|
1211
|
+
if (t.type === 'credential_regex_harvest' && (t.severity === 'HIGH' || t.severity === 'CRITICAL')) {
|
|
1212
|
+
t.reductions.push({ rule: 'sink_coupling', from: t.severity, to: 'LOW' });
|
|
1213
|
+
t.severity = 'LOW';
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1177
1218
|
for (const t of threats) {
|
|
1178
1219
|
|
|
1179
1220
|
// Audit v3 B3: typosquat with LOW confidence → MEDIUM
|