muaddib-scanner 2.10.74 → 2.10.78
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/monitor/queue.js
CHANGED
|
@@ -804,7 +804,6 @@ async function scanPackage(name, version, ecosystem, tarballUrl, registryMeta, s
|
|
|
804
804
|
appendDetection(name, version, ecosystem, findingTypes, maxSeverity);
|
|
805
805
|
recordTrainingSample(result, { name, version, ecosystem, label: 'suspect', tier, sandboxResult, registryMeta: meta, unpackedSize: meta.unpackedSize, npmRegistryMeta, fileCountTotal, hasTests });
|
|
806
806
|
|
|
807
|
-
dailyAlerts.push({ name, version, ecosystem, findingsCount: result.summary.total, tier });
|
|
808
807
|
// Persist alert locally for ALL suspects (independent of webhook filtering)
|
|
809
808
|
const alertData = buildAlertData(name, version, ecosystem, result, sandboxResult);
|
|
810
809
|
persistAlert(name, version, ecosystem, alertData);
|
|
@@ -832,6 +831,9 @@ async function scanPackage(name, version, ecosystem, tarballUrl, registryMeta, s
|
|
|
832
831
|
} else if (ecosystem === 'npm' && hasHighConfidenceThreat(result)) {
|
|
833
832
|
console.log(`[MONITOR] REPUTATION BYPASS: ${name} has high-confidence threat — using raw score`);
|
|
834
833
|
}
|
|
834
|
+
|
|
835
|
+
// Record daily alert with post-reputation score for top suspects ranking
|
|
836
|
+
dailyAlerts.push({ name, version, ecosystem, findingsCount: result.summary.total, score: adjustedResult.summary.riskScore || 0, tier });
|
|
835
837
|
// LLM Detective: AI-powered analysis for T1a/T1b suspects
|
|
836
838
|
let llmResult = null;
|
|
837
839
|
if ((tier === '1a' || tier === '1b') && (adjustedResult.summary.riskScore || 0) >= 25) {
|
package/src/monitor/webhook.js
CHANGED
|
@@ -794,7 +794,7 @@ function buildDailyReportEmbed(stats, dailyAlerts) {
|
|
|
794
794
|
|
|
795
795
|
// Prefer in-memory dailyAlerts for top suspects (richer data), fallback to disk
|
|
796
796
|
const top3 = dailyAlerts.length > 0
|
|
797
|
-
? dailyAlerts.slice().sort((a, b) => b.findingsCount - a.findingsCount).slice(0, 3)
|
|
797
|
+
? dailyAlerts.slice().sort((a, b) => (b.score || 0) - (a.score || 0) || b.findingsCount - a.findingsCount).slice(0, 3)
|
|
798
798
|
: diskTop3;
|
|
799
799
|
|
|
800
800
|
const top3Text = top3.length > 0
|
|
@@ -802,7 +802,8 @@ function buildDailyReportEmbed(stats, dailyAlerts) {
|
|
|
802
802
|
const name = a.ecosystem ? `${a.ecosystem}/${a.name || a.package}` : (a.name || a.package);
|
|
803
803
|
const version = a.version || 'N/A';
|
|
804
804
|
const count = a.findingsCount || (a.findings ? a.findings.length : 0);
|
|
805
|
-
|
|
805
|
+
const scoreText = a.score != null ? `score ${a.score}, ` : '';
|
|
806
|
+
return `${i + 1}. **${name}@${version}** — ${scoreText}${count} finding(s)`;
|
|
806
807
|
}).join('\n')
|
|
807
808
|
: 'None';
|
|
808
809
|
|
|
@@ -946,7 +947,7 @@ async function sendDailyReport(stats, dailyAlerts, recentlyScanned, downloadsCac
|
|
|
946
947
|
deferredProcessed: stats.deferredProcessed || 0,
|
|
947
948
|
deferredExpired: stats.deferredExpired || 0,
|
|
948
949
|
changesStreamPackages: stats.changesStreamPackages || 0,
|
|
949
|
-
topSuspects: dailyAlerts.slice().sort((a, b) => b.findingsCount - a.findingsCount).slice(0, 10)
|
|
950
|
+
topSuspects: dailyAlerts.slice().sort((a, b) => (b.score || 0) - (a.score || 0) || b.findingsCount - a.findingsCount).slice(0, 10)
|
|
950
951
|
});
|
|
951
952
|
|
|
952
953
|
// Send webhook only if configured
|
|
@@ -39,16 +39,37 @@
|
|
|
39
39
|
// fesm*/, esm/, esm5/, esm2015/, esm2020/, bundles/, assets/, chunks/, _app/)
|
|
40
40
|
// - Basename suffixes (.min.js, .bundle.js, .umd.js, .esm.js, .es.js,
|
|
41
41
|
// .common.js, .max.js, .prod.js, .production.js, + .cjs / .mjs variants)
|
|
42
|
+
// - Double-extension bundler outputs (index.cjs.js, index.esm.js, index.umd.js
|
|
43
|
+
// at package root — common pattern for @equinor/*, tsdx/rollup bundled libs)
|
|
42
44
|
// - Hash-suffixed chunks (esbuild/vite/rollup/webpack convention):
|
|
43
45
|
// `basename-[a-f0-9]{6,16}.js|mjs|cjs`
|
|
46
|
+
// - Tool-specific subdirectories that contain vendored bundles (v2.10.75):
|
|
47
|
+
// * `lib/[name]Bundle*/` — Playwright-style `lib/utilsBundleImpl/`
|
|
48
|
+
// * `.yarn/releases/` — vendored yarn/pnpm releases shipped in template packages
|
|
49
|
+
// * `sys/(node|browser|deno)/` — Stencil-style platform-specific bundle
|
|
50
|
+
// * `compiled/` — SWC/Stencil compiled output
|
|
51
|
+
// * `typings/` — only if matches a .d.ts file (defensive)
|
|
44
52
|
const BUNDLE_PATH_RE = new RegExp(
|
|
45
|
-
// Path prefix group
|
|
53
|
+
// Path prefix group (directories that almost always contain bundled output)
|
|
46
54
|
'(?:^|[/\\\\])' +
|
|
47
|
-
'(?:dist|build|out|output|browser|bundles|assets|chunks|_app|' +
|
|
55
|
+
'(?:dist|build|out|output|browser|bundles|assets|chunks|_app|compiled|' +
|
|
48
56
|
'lib[/\\\\]bundled|fesm\\d*|esm|esm5|esm2015|esm2020)' +
|
|
49
57
|
'[/\\\\]' +
|
|
50
|
-
// OR
|
|
51
|
-
|
|
58
|
+
// OR Playwright-style lib/xxxBundle*/ (e.g. lib/utilsBundleImpl/, lib/mcpBundleImpl/,
|
|
59
|
+
// lib/transform/babelBundleImpl.js) — matches the directory form
|
|
60
|
+
// `lib/.../xxxBundleImpl/index.js` and the flat form `lib/.../xxxBundleImpl.js`
|
|
61
|
+
// at any depth under lib/.
|
|
62
|
+
'|(?:^|[/\\\\])lib[/\\\\][^\\n]*[Bb]undle[\\w-]*(?:[/\\\\]|\\.(?:m?js|cjs)$)' +
|
|
63
|
+
// OR vendored yarn/pnpm releases (@backstage/create-app templates etc.)
|
|
64
|
+
'|(?:^|[/\\\\])\\.yarn[/\\\\]releases[/\\\\]' +
|
|
65
|
+
'|(?:^|[/\\\\])\\.pnpm[/\\\\](?:releases|dist)[/\\\\]' +
|
|
66
|
+
// OR Stencil-style sys/(node|browser|deno) containing compiled platform bundles
|
|
67
|
+
'|(?:^|[/\\\\])sys[/\\\\](?:node|browser|deno)[/\\\\]' +
|
|
68
|
+
// OR basename suffix group (single extension)
|
|
69
|
+
'|\\.(?:min|bundle|umd|esm|es|cjs|common|max|prod|production|iife)\\.(?:m?js|cjs)$' +
|
|
70
|
+
// OR double-extension bundler outputs at root: index.cjs.js, index.esm.js, etc.
|
|
71
|
+
// Anchored by `^` or path separator + basename with exactly the double extension.
|
|
72
|
+
'|(?:^|[/\\\\])[\\w-]+\\.(?:cjs|esm|umd|es|iife|min)\\.js$' +
|
|
52
73
|
// OR hash-suffixed chunk
|
|
53
74
|
'|(?:^|[/\\\\])[\\w-]+[-.][a-f0-9]{6,16}\\.(?:m?js|cjs)$',
|
|
54
75
|
'i'
|
|
@@ -131,6 +152,13 @@ function hasBundleVetoSignal(threats, targetFile) {
|
|
|
131
152
|
if (!Array.isArray(threats) || !targetFile) return false;
|
|
132
153
|
for (const t of threats) {
|
|
133
154
|
if (t.file !== targetFile) continue;
|
|
155
|
+
// v2.10.75 fix: a LOW severity threat should never block the bundle downgrade
|
|
156
|
+
// of unrelated co-occurring threats. Typical regression case: a locale file
|
|
157
|
+
// (locales/fa-IR/*.js) contains `unicode_invisible_injection` at LOW (already
|
|
158
|
+
// downgraded by `isLocaleFile` in obfuscation.js) but also contains bundler
|
|
159
|
+
// helpers. Before this fix, the LOW unicode signal vetoed the bundle downgrade
|
|
160
|
+
// of the other threats, so the package scored higher than pre-v2.10.74.
|
|
161
|
+
if (t.severity === 'LOW') continue;
|
|
134
162
|
if (VETO_TYPES.has(t.type)) return true;
|
|
135
163
|
if (t.type === 'env_access' && t.message && SENSITIVE_ENV_RE.test(t.message)) {
|
|
136
164
|
return true;
|