devcompass 2.7.0 → 2.7.1
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 +2 -2
- package/src/analyzers/supply-chain.js +37 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devcompass",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Dependency health checker with ecosystem intelligence, real-time GitHub issue tracking for 500+ popular npm packages, parallel processing, supply chain security analysis, and advanced license risk detection.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -76,4 +76,4 @@
|
|
|
76
76
|
"url": "https://github.com/AjayBThorat-20/devcompass/issues"
|
|
77
77
|
},
|
|
78
78
|
"homepage": "https://github.com/AjayBThorat-20/devcompass#readme"
|
|
79
|
-
}
|
|
79
|
+
}
|
|
@@ -54,45 +54,51 @@ function levenshteinDistance(str1, str2) {
|
|
|
54
54
|
/**
|
|
55
55
|
* Detect typosquatting attempts
|
|
56
56
|
*/
|
|
57
|
-
function detectTyposquatting(packageName,
|
|
57
|
+
function detectTyposquatting(packageName, packageVersion, maliciousDb) {
|
|
58
58
|
const warnings = [];
|
|
59
59
|
|
|
60
|
+
// Whitelist of legitimate popular packages that might have similar names
|
|
61
|
+
// These should NEVER be flagged as typosquatting
|
|
62
|
+
const LEGITIMATE_PACKAGES = [
|
|
63
|
+
'chalk', 'chai', 'ora', 'yargs', 'meow', 'execa', 'globby', 'del', 'make-dir',
|
|
64
|
+
'p-map', 'p-limit', 'p-queue', 'got', 'ky', 'node-fetch', 'cross-fetch',
|
|
65
|
+
'uuid', 'nanoid', 'cuid', 'luxon', 'date-fns', 'ms', 'bytes', 'filesize',
|
|
66
|
+
'fast-glob', 'chokidar', 'picomatch', 'micromatch', 'anymatch',
|
|
67
|
+
'semver', 'commander', 'yargs', 'inquirer', 'prompts', 'enquirer',
|
|
68
|
+
'debug', 'pino', 'winston', 'bunyan', 'signale'
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
// Skip whitelist packages
|
|
72
|
+
if (LEGITIMATE_PACKAGES.includes(packageName)) {
|
|
73
|
+
return warnings;
|
|
74
|
+
}
|
|
75
|
+
|
|
60
76
|
// Check against known typosquat patterns
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
// typosquat_patterns is an object: { "express": ["epress", "expres"], ... }
|
|
78
|
+
const patterns = maliciousDb.typosquat_patterns || {};
|
|
79
|
+
|
|
80
|
+
for (const officialName of Object.keys(patterns)) {
|
|
81
|
+
// Skip if the official package is also whitelisted (both are legitimate)
|
|
82
|
+
// This prevents false positives like "chalk" vs "chai"
|
|
83
|
+
if (LEGITIMATE_PACKAGES.includes(officialName)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const distance = levenshteinDistance(packageName, officialName);
|
|
88
|
+
|
|
89
|
+
// Flag if 1-2 character difference (typosquatting likely)
|
|
90
|
+
if (distance > 0 && distance <= 2 && packageName !== officialName) {
|
|
63
91
|
warnings.push({
|
|
64
|
-
package: packageName
|
|
92
|
+
package: `${packageName}@${packageVersion}`,
|
|
65
93
|
type: 'typosquatting',
|
|
66
|
-
severity: 'high',
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
94
|
+
severity: distance === 1 ? 'high' : 'medium',
|
|
95
|
+
message: `Similar to: ${officialName} (official package)`,
|
|
96
|
+
recommendation: `Verify if you meant to install ${officialName}`,
|
|
97
|
+
official: officialName
|
|
70
98
|
});
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
|
|
74
|
-
// Check Levenshtein distance against popular packages
|
|
75
|
-
const popularPackages = Object.keys(database.typosquat_patterns);
|
|
76
|
-
for (const popular of popularPackages) {
|
|
77
|
-
const distance = levenshteinDistance(packageName.toLowerCase(), popular.toLowerCase());
|
|
78
|
-
|
|
79
|
-
// If distance is 1-2 characters and not already flagged
|
|
80
|
-
if (distance > 0 && distance <= 2 && packageName !== popular) {
|
|
81
|
-
const alreadyFlagged = warnings.some(w => w.package === packageName);
|
|
82
|
-
|
|
83
|
-
if (!alreadyFlagged) {
|
|
84
|
-
warnings.push({
|
|
85
|
-
package: packageName,
|
|
86
|
-
type: 'typosquatting_suspected',
|
|
87
|
-
severity: 'medium',
|
|
88
|
-
official: popular,
|
|
89
|
-
message: `Possible typosquatting: "${packageName}" is very similar to "${popular}"`,
|
|
90
|
-
recommendation: `Verify if you meant to install ${popular}`
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
102
|
return warnings;
|
|
97
103
|
}
|
|
98
104
|
|
|
@@ -181,7 +187,7 @@ async function analyzeSupplyChain(projectPath, dependencies) {
|
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
// 2. Detect typosquatting
|
|
184
|
-
const typosquatWarnings = detectTyposquatting(packageName, database);
|
|
190
|
+
const typosquatWarnings = detectTyposquatting(packageName, version, database);
|
|
185
191
|
warnings.push(...typosquatWarnings);
|
|
186
192
|
}
|
|
187
193
|
|