muaddib-scanner 2.11.116 → 2.11.117
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/scanner/typosquat.js
CHANGED
|
@@ -73,6 +73,23 @@ const LEGIT_BOUNDARY_TOKENS = new Set([
|
|
|
73
73
|
'v2', 'v3', 'v4', 'next', 'latest', 'stable', 'lts', 'legacy', 'beta', 'alpha'
|
|
74
74
|
]);
|
|
75
75
|
|
|
76
|
+
// RT-C1-FPR (2026-06, n=61 blind adjudication → boundary-squat measured 100% FP): popular
|
|
77
|
+
// packages whose names are GENERIC tech/English words appear as a legitimate TRAILING token
|
|
78
|
+
// in countless real packages — class-validator, graphile-config, ansi-colors, sinon-chai,
|
|
79
|
+
// react-helmet-async, swagger-ui-express, short-uuid, react-router-redux, openapi-typescript,
|
|
80
|
+
// tree-sitter-c-sharp, agent-commander. Suffix boundary-squat on these is unreliable, so they
|
|
81
|
+
// are NOT matched. Distinctive brand names (axios, lodash, chalk, crypto-js — incl. the
|
|
82
|
+
// plain-crypto-js / secure-axios FN-guards) stay matchable. A genuine `<x>-<generic>` squat is
|
|
83
|
+
// caught by its CODE (exfil/RCE + the Track-R malice floor), not by name shape (see below).
|
|
84
|
+
const GENERIC_POPULAR_NAMES = new Set([
|
|
85
|
+
'validator', 'config', 'colors', 'async', 'chai', 'typescript', 'request', 'uuid',
|
|
86
|
+
'redux', 'express', 'sharp', 'commander', 'debug', 'glob', 'yaml', 'cors', 'helmet',
|
|
87
|
+
'canvas', 'immutable', 'classnames',
|
|
88
|
+
// Infra/framework brands that are also common legit trailing tokens (rate-limit-redis,
|
|
89
|
+
// connect-redis, shadcn-svelte, authentikt-svelte) — same measured-FP class, same FN floor.
|
|
90
|
+
'redis', 'svelte',
|
|
91
|
+
]);
|
|
92
|
+
|
|
76
93
|
// Packages legitimes courts ou qui ressemblent a des populaires
|
|
77
94
|
const WHITELIST = new Set([
|
|
78
95
|
// Packages tres courts legitimes
|
|
@@ -456,14 +473,13 @@ function findDependencyBoundarySquat(name) {
|
|
|
456
473
|
if (lower === popular) continue;
|
|
457
474
|
|
|
458
475
|
if (popular.includes('-')) {
|
|
459
|
-
// Multi-token popular (e.g. crypto-js):
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
if (extra === null || extra.length === 0) continue;
|
|
476
|
+
// Multi-token popular (e.g. crypto-js): a squat PREPENDS a deceptive qualifier
|
|
477
|
+
// (plain-crypto-js → endsWith). The reverse `<popular>-<suffix>` (date-fns-tz,
|
|
478
|
+
// aws-sdk-client-mock, core-js-compat) is the popular package's OWN ecosystem extension —
|
|
479
|
+
// never a squat — so the prefix-position match is dropped (2026-06 FPR fix, 100% FP).
|
|
480
|
+
if (!lower.endsWith('-' + popular)) continue;
|
|
481
|
+
const extra = lower.slice(0, lower.length - popular.length - 1);
|
|
482
|
+
if (extra.length === 0) continue;
|
|
467
483
|
// Reject if extra is a legit boundary token (single token only)
|
|
468
484
|
if (!extra.includes('-') && LEGIT_BOUNDARY_TOKENS.has(extra)) continue;
|
|
469
485
|
return { original: POPULAR_PACKAGES[i], type: 'boundary_squat', distance: extra.length, extra };
|
|
@@ -480,6 +496,10 @@ function findDependencyBoundarySquat(name) {
|
|
|
480
496
|
const tokens = lower.split('-');
|
|
481
497
|
if (tokens.length === 1) continue;
|
|
482
498
|
if (tokens[tokens.length - 1] !== popular) continue; // popular must be the trailing token
|
|
499
|
+
// Generic-word popular (validator/config/colors/async/chai/typescript/...) is a common
|
|
500
|
+
// legitimate trailing token (class-validator, graphile-config, ansi-colors) — 100% FP in
|
|
501
|
+
// the 2026-06 measurement. Distinctive brands (axios → secure-axios FN-guard) still match.
|
|
502
|
+
if (GENERIC_POPULAR_NAMES.has(popular)) continue;
|
|
483
503
|
const siblings = tokens.slice(0, -1);
|
|
484
504
|
// Benign ecosystem variant if every prefix token is a legit qualifier (ts-jest, babel-jest).
|
|
485
505
|
if (siblings.every(t => LEGIT_BOUNDARY_TOKENS.has(t) || isLegitimateVariant(t))) continue;
|