muaddib-scanner 2.11.94 → 2.11.95
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
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
const dns = require('dns');
|
|
19
19
|
const { debugLog } = require('../utils.js');
|
|
20
|
-
const { isShadowEnabled, recordShadowDivergence } = require('../shared/shadow.js');
|
|
21
20
|
|
|
22
21
|
const MX_TIMEOUT_MS = 3000;
|
|
23
22
|
const MX_CACHE_TTL = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
@@ -226,8 +225,11 @@ async function fetchRdap(domain, options = {}) {
|
|
|
226
225
|
}
|
|
227
226
|
|
|
228
227
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
228
|
+
* @deprecated Retired from the production emission path by the 2026-06-11 V2
|
|
229
|
+
* flip — `checkCompromisedDomain` now emits via `isCompromisedDomainV2`. Kept
|
|
230
|
+
* (exported + unit-tested) as the documented former semantics: creation AFTER
|
|
231
|
+
* first publish with a 30-day pre-publish margin. The margin was the source of
|
|
232
|
+
* ~23% of historical FPs (a dev buying a domain weeks before shipping v1).
|
|
231
233
|
*/
|
|
232
234
|
function isCompromisedDomain(creationDateISO, packageCreatedAtISO) {
|
|
233
235
|
if (!creationDateISO || !packageCreatedAtISO) return false;
|
|
@@ -292,12 +294,16 @@ function isCompromisedDomainV2(creationDateISO, firstPublishISO, domain) {
|
|
|
292
294
|
}
|
|
293
295
|
|
|
294
296
|
/**
|
|
295
|
-
* F1 entry point
|
|
297
|
+
* F1 entry point — emits `compromised_email_domain` (HIGH×high = 10, composite-only:
|
|
298
|
+
* sub-T1, and the tier-1b corroboration gate requires ≥2 distinct signals). LIVE
|
|
299
|
+
* semantics since 2026-06-11 = `isCompromisedDomainV2` (strict creation > first
|
|
300
|
+
* publish, public email providers excluded). The former V1 30-day-margin
|
|
301
|
+
* semantics is retired (see isCompromisedDomain @deprecated).
|
|
296
302
|
* @param {object|null} meta - Digested metadata. Reads maintainer_emails + created_at
|
|
297
303
|
* (= the package's FIRST publish date, both npm and PyPI sides).
|
|
298
304
|
* @param {object} options - { fetchRdap } for tests to inject a mock.
|
|
299
|
-
* { shadowCtx
|
|
300
|
-
*
|
|
305
|
+
* { shadowCtx } is accepted but ignored since the flip (kept so existing callers
|
|
306
|
+
* in processor.js / pypi-maintainer.js need no change).
|
|
301
307
|
* @returns {Promise<Array>} threats array
|
|
302
308
|
*/
|
|
303
309
|
async function checkCompromisedDomain(meta, options = {}) {
|
|
@@ -321,25 +327,12 @@ async function checkCompromisedDomain(meta, options = {}) {
|
|
|
321
327
|
continue;
|
|
322
328
|
}
|
|
323
329
|
if (!rdap || !rdap.creationDate) continue;
|
|
324
|
-
//
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const v2 = isCompromisedDomainV2(rdap.creationDate, meta.created_at, domain);
|
|
331
|
-
if (v1 !== v2) {
|
|
332
|
-
const ctx = options.shadowCtx || {};
|
|
333
|
-
recordShadowDivergence({
|
|
334
|
-
detector: 'compromised_email_domain',
|
|
335
|
-
package: ctx.name, version: ctx.version, ecosystem: ctx.ecosystem,
|
|
336
|
-
oldVerdict: v1, newVerdict: v2,
|
|
337
|
-
evidence: { domain, creationDate: rdap.creationDate, firstPublish: meta.created_at, oldMarginDays: 30 }
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
} catch { /* shadow must never affect the scan */ }
|
|
342
|
-
if (isCompromisedDomain(rdap.creationDate, meta.created_at)) {
|
|
330
|
+
// V2 is the LIVE semantics since the 2026-06-11 flip (backtest #545 era:
|
|
331
|
+
// V2 strict-creation + public-provider exclusion killed 307/1346 historical
|
|
332
|
+
// FP alerts — the @tronweb3/* wallet-adapter monorepo flood — and added 0
|
|
333
|
+
// new flags / 0 FN; V2 ⊂ V1, so no shadow net is needed). The old V1 margin
|
|
334
|
+
// shadow hook is retired with the flip.
|
|
335
|
+
if (isCompromisedDomainV2(rdap.creationDate, meta.created_at, domain)) {
|
|
343
336
|
const cd = rdap.creationDate.slice(0, 10);
|
|
344
337
|
const pd = meta.created_at.slice(0, 10);
|
|
345
338
|
threats.push({
|