safe-pkg 1.0.0

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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +304 -0
  3. package/dist/.DS_Store +0 -0
  4. package/dist/cli/index.d.ts +5 -0
  5. package/dist/cli/index.js +135 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/parser.d.ts +5 -0
  8. package/dist/cli/parser.js +61 -0
  9. package/dist/cli/parser.js.map +1 -0
  10. package/dist/config/index.d.ts +1 -0
  11. package/dist/config/index.js +3 -0
  12. package/dist/config/index.js.map +1 -0
  13. package/dist/config/loadConfig.d.ts +5 -0
  14. package/dist/config/loadConfig.js +49 -0
  15. package/dist/config/loadConfig.js.map +1 -0
  16. package/dist/detector/detectPackageManager.d.ts +14 -0
  17. package/dist/detector/detectPackageManager.js +68 -0
  18. package/dist/detector/detectPackageManager.js.map +1 -0
  19. package/dist/detector/index.d.ts +1 -0
  20. package/dist/detector/index.js +3 -0
  21. package/dist/detector/index.js.map +1 -0
  22. package/dist/executor/index.d.ts +1 -0
  23. package/dist/executor/index.js +3 -0
  24. package/dist/executor/index.js.map +1 -0
  25. package/dist/executor/runCommand.d.ts +9 -0
  26. package/dist/executor/runCommand.js +61 -0
  27. package/dist/executor/runCommand.js.map +1 -0
  28. package/dist/index.d.ts +8 -0
  29. package/dist/index.js +11 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/scanner/aiAnalyzer.d.ts +6 -0
  32. package/dist/scanner/aiAnalyzer.js +92 -0
  33. package/dist/scanner/aiAnalyzer.js.map +1 -0
  34. package/dist/scanner/analyzePackage.d.ts +5 -0
  35. package/dist/scanner/analyzePackage.js +155 -0
  36. package/dist/scanner/analyzePackage.js.map +1 -0
  37. package/dist/scanner/auditAnalyzer.d.ts +11 -0
  38. package/dist/scanner/auditAnalyzer.js +113 -0
  39. package/dist/scanner/auditAnalyzer.js.map +1 -0
  40. package/dist/scanner/heuristicAnalyzer.d.ts +5 -0
  41. package/dist/scanner/heuristicAnalyzer.js +228 -0
  42. package/dist/scanner/heuristicAnalyzer.js.map +1 -0
  43. package/dist/scanner/index.d.ts +6 -0
  44. package/dist/scanner/index.js +8 -0
  45. package/dist/scanner/index.js.map +1 -0
  46. package/dist/scanner/metadataAnalyzer.d.ts +5 -0
  47. package/dist/scanner/metadataAnalyzer.js +136 -0
  48. package/dist/scanner/metadataAnalyzer.js.map +1 -0
  49. package/dist/scanner/scriptAnalyzer.d.ts +5 -0
  50. package/dist/scanner/scriptAnalyzer.js +187 -0
  51. package/dist/scanner/scriptAnalyzer.js.map +1 -0
  52. package/dist/scanner-project/batchAnalyze.d.ts +1 -0
  53. package/dist/scanner-project/batchAnalyze.js +4 -0
  54. package/dist/scanner-project/batchAnalyze.js.map +1 -0
  55. package/dist/scanner-project/index.d.ts +4 -0
  56. package/dist/scanner-project/index.js +6 -0
  57. package/dist/scanner-project/index.js.map +1 -0
  58. package/dist/scanner-project/readDependencies.d.ts +5 -0
  59. package/dist/scanner-project/readDependencies.js +28 -0
  60. package/dist/scanner-project/readDependencies.js.map +1 -0
  61. package/dist/scanner-project/scanNodeModules.d.ts +1 -0
  62. package/dist/scanner-project/scanNodeModules.js +4 -0
  63. package/dist/scanner-project/scanNodeModules.js.map +1 -0
  64. package/dist/scanner-project/scanProject.d.ts +5 -0
  65. package/dist/scanner-project/scanProject.js +69 -0
  66. package/dist/scanner-project/scanProject.js.map +1 -0
  67. package/dist/test.d.ts +6 -0
  68. package/dist/test.js +153 -0
  69. package/dist/test.js.map +1 -0
  70. package/dist/types.d.ts +133 -0
  71. package/dist/types.js +2 -0
  72. package/dist/types.js.map +1 -0
  73. package/dist/ui/index.d.ts +4 -0
  74. package/dist/ui/index.js +6 -0
  75. package/dist/ui/index.js.map +1 -0
  76. package/dist/ui/logger.d.ts +24 -0
  77. package/dist/ui/logger.js +39 -0
  78. package/dist/ui/logger.js.map +1 -0
  79. package/dist/ui/promptUser.d.ts +12 -0
  80. package/dist/ui/promptUser.js +50 -0
  81. package/dist/ui/promptUser.js.map +1 -0
  82. package/dist/ui/riskReporter.d.ts +5 -0
  83. package/dist/ui/riskReporter.js +157 -0
  84. package/dist/ui/riskReporter.js.map +1 -0
  85. package/dist/ui/scanReporter.d.ts +1 -0
  86. package/dist/ui/scanReporter.js +4 -0
  87. package/dist/ui/scanReporter.js.map +1 -0
  88. package/package.json +61 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Popular legitimate packages (for typosquatting detection)
3
+ */
4
+ const POPULAR_PACKAGES = [
5
+ "react",
6
+ "vue",
7
+ "angular",
8
+ "express",
9
+ "lodash",
10
+ "axios",
11
+ "moment",
12
+ "webpack",
13
+ "babel",
14
+ "eslint",
15
+ "prettier",
16
+ "typescript",
17
+ "jquery",
18
+ "chalk",
19
+ "commander",
20
+ "next",
21
+ "gatsby",
22
+ "nuxt",
23
+ "svelte",
24
+ "redux",
25
+ ];
26
+ /**
27
+ * Suspicious keywords in package names
28
+ */
29
+ const SUSPICIOUS_KEYWORDS = [
30
+ "hack",
31
+ "crack",
32
+ "keygen",
33
+ "exploit",
34
+ "backdoor",
35
+ "malware",
36
+ "virus",
37
+ "trojan",
38
+ "stealer",
39
+ "miner",
40
+ "cryptominer",
41
+ "bitcoin",
42
+ "wallet-stealer",
43
+ "free-premium",
44
+ "pro-unlimited",
45
+ "cracked",
46
+ ];
47
+ /**
48
+ * Suspicious patterns in package names
49
+ */
50
+ const SUSPICIOUS_PATTERNS = [
51
+ /^[a-z0-9-]{50,}$/, // Extremely long random names
52
+ /^[0-9]+$/, // All numbers
53
+ /([a-z])\1{4,}/, // Repeated characters (aaaaa)
54
+ /^(test|tmp|temp|demo|sample)-/, // Temporary/test packages
55
+ /-+admin-*$/i, // Ends with admin
56
+ /-+pro-*max/i, // Contains "pro max" marketing spam
57
+ /free.*premium/i, // "free premium" scam
58
+ /unlimited.*crack/i, // "unlimited crack"
59
+ ];
60
+ /**
61
+ * Analyze package name using heuristic patterns
62
+ */
63
+ export function analyzeHeuristics(packageName) {
64
+ const suspiciousPatterns = [];
65
+ let riskScore = 0;
66
+ // Check for suspicious keywords
67
+ const foundKeywords = checkSuspiciousKeywords(packageName);
68
+ if (foundKeywords.length > 0) {
69
+ suspiciousPatterns.push(`Suspicious keywords: ${foundKeywords.join(", ")}`);
70
+ riskScore += foundKeywords.length * 3; // 3 points per suspicious keyword
71
+ }
72
+ // Check for suspicious patterns
73
+ const foundPatterns = checkSuspiciousPatterns(packageName);
74
+ if (foundPatterns.length > 0) {
75
+ suspiciousPatterns.push(...foundPatterns);
76
+ riskScore += foundPatterns.length * 2; // 2 points per pattern
77
+ }
78
+ // Check for typosquatting
79
+ const typosquatResult = checkTyposquatting(packageName);
80
+ if (typosquatResult.isPotentialTyposquat) {
81
+ suspiciousPatterns.push(`Possible typosquatting of: ${typosquatResult.similarTo}`);
82
+ riskScore += 4; // High risk for typosquatting
83
+ }
84
+ // Check for excessive hyphens/numbers
85
+ const hyphenCount = (packageName.match(/-/g) || []).length;
86
+ const numberCount = (packageName.match(/[0-9]/g) || []).length;
87
+ if (hyphenCount > 4) {
88
+ suspiciousPatterns.push(`Excessive hyphens (${hyphenCount})`);
89
+ riskScore += 1;
90
+ }
91
+ if (numberCount > packageName.length / 2) {
92
+ suspiciousPatterns.push("Too many numbers in name");
93
+ riskScore += 1;
94
+ }
95
+ // Check for mixed case spam (e.g., "rEaCt-FrEe")
96
+ if (/[A-Z]/.test(packageName) && /[a-z]/.test(packageName)) {
97
+ const upperCount = (packageName.match(/[A-Z]/g) || []).length;
98
+ const lowerCount = (packageName.match(/[a-z]/g) || []).length;
99
+ if (upperCount > 2 && upperCount < lowerCount) {
100
+ suspiciousPatterns.push("Mixed case pattern (possible spam)");
101
+ riskScore += 1;
102
+ }
103
+ }
104
+ // Cap score at 10
105
+ riskScore = Math.min(riskScore, 10);
106
+ return {
107
+ suspiciousPatterns,
108
+ isPotentialTyposquat: typosquatResult.isPotentialTyposquat,
109
+ riskScore: riskScore,
110
+ };
111
+ }
112
+ /**
113
+ * Check for suspicious keywords in package name
114
+ */
115
+ function checkSuspiciousKeywords(packageName) {
116
+ const lowerName = packageName.toLowerCase();
117
+ return SUSPICIOUS_KEYWORDS.filter((keyword) => lowerName.includes(keyword));
118
+ }
119
+ /**
120
+ * Check for suspicious patterns in package name
121
+ */
122
+ function checkSuspiciousPatterns(packageName) {
123
+ const patterns = [];
124
+ for (const pattern of SUSPICIOUS_PATTERNS) {
125
+ if (pattern.test(packageName)) {
126
+ patterns.push(`Matches suspicious pattern: ${pattern.source}`);
127
+ }
128
+ }
129
+ return patterns;
130
+ }
131
+ /**
132
+ * Check if package name is potentially typosquatting a popular package
133
+ */
134
+ function checkTyposquatting(packageName) {
135
+ const lowerName = packageName.toLowerCase();
136
+ for (const popularPkg of POPULAR_PACKAGES) {
137
+ // Exact match is not typosquatting
138
+ if (lowerName === popularPkg.toLowerCase()) {
139
+ continue;
140
+ }
141
+ // Check Levenshtein distance
142
+ const distance = levenshteinDistance(lowerName, popularPkg.toLowerCase());
143
+ // If distance is 1-2, it's likely typosquatting
144
+ if (distance <= 2 && distance > 0) {
145
+ return {
146
+ isPotentialTyposquat: true,
147
+ similarTo: popularPkg,
148
+ };
149
+ }
150
+ // Check for common typosquatting techniques
151
+ if (checkCommonTyposquattingTechniques(lowerName, popularPkg)) {
152
+ return {
153
+ isPotentialTyposquat: true,
154
+ similarTo: popularPkg,
155
+ };
156
+ }
157
+ }
158
+ return {
159
+ isPotentialTyposquat: false,
160
+ };
161
+ }
162
+ /**
163
+ * Calculate Levenshtein distance between two strings
164
+ */
165
+ function levenshteinDistance(str1, str2) {
166
+ const len1 = str1.length;
167
+ const len2 = str2.length;
168
+ // Create matrix with proper initialization
169
+ const matrix = [];
170
+ for (let i = 0; i <= len1; i++) {
171
+ matrix[i] = new Array(len2 + 1).fill(0);
172
+ }
173
+ // Initialize first column and row
174
+ for (let i = 0; i <= len1; i++) {
175
+ const row = matrix[i];
176
+ if (row)
177
+ row[0] = i;
178
+ }
179
+ for (let j = 0; j <= len2; j++) {
180
+ const row = matrix[0];
181
+ if (row)
182
+ row[j] = j;
183
+ }
184
+ // Fill matrix
185
+ for (let i = 1; i <= len1; i++) {
186
+ for (let j = 1; j <= len2; j++) {
187
+ const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
188
+ const currentRow = matrix[i];
189
+ const prevRow = matrix[i - 1];
190
+ if (currentRow && prevRow) {
191
+ const deletion = (prevRow[j] ?? 0) + 1;
192
+ const insertion = (currentRow[j - 1] ?? 0) + 1;
193
+ const substitution = (prevRow[j - 1] ?? 0) + cost;
194
+ currentRow[j] = Math.min(deletion, insertion, substitution);
195
+ }
196
+ }
197
+ }
198
+ const finalRow = matrix[len1];
199
+ return finalRow ? finalRow[len2] ?? 0 : 0;
200
+ }
201
+ /**
202
+ * Check for common typosquatting techniques
203
+ */
204
+ function checkCommonTyposquattingTechniques(packageName, popularPkg) {
205
+ // Adding prefix/suffix
206
+ if (packageName.startsWith(popularPkg) || packageName.endsWith(popularPkg)) {
207
+ const diff = packageName.replace(popularPkg, "");
208
+ // If the difference is small and looks like spam
209
+ if (diff.length <= 5 && /^[-_0-9]+$/.test(diff)) {
210
+ return true;
211
+ }
212
+ }
213
+ // Character substitution (l -> 1, o -> 0, etc.)
214
+ const normalized = packageName
215
+ .replace(/1/g, "l")
216
+ .replace(/0/g, "o")
217
+ .replace(/5/g, "s");
218
+ if (normalized === popularPkg) {
219
+ return true;
220
+ }
221
+ // Extra hyphen/underscore
222
+ const withoutSeparators = packageName.replace(/[-_]/g, "");
223
+ if (withoutSeparators === popularPkg.replace(/[-_]/g, "")) {
224
+ return true;
225
+ }
226
+ return false;
227
+ }
228
+ //# sourceMappingURL=heuristicAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heuristicAnalyzer.js","sourceRoot":"","sources":["../../src/scanner/heuristicAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from "./analyzePackage.js";
2
+ export { analyzeWithAudit, analyzePackageAudit } from "./auditAnalyzer.js";
3
+ export * from "./metadataAnalyzer.js";
4
+ export * from "./scriptAnalyzer.js";
5
+ export * from "./heuristicAnalyzer.js";
6
+ export * from "./aiAnalyzer.js";
@@ -0,0 +1,8 @@
1
+ // Scanner barrel exports
2
+ export * from "./analyzePackage.js";
3
+ export { analyzeWithAudit, analyzePackageAudit } from "./auditAnalyzer.js";
4
+ export * from "./metadataAnalyzer.js";
5
+ export * from "./scriptAnalyzer.js";
6
+ export * from "./heuristicAnalyzer.js";
7
+ export * from "./aiAnalyzer.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { MetadataScore } from "../types.js";
2
+ /**
3
+ * Analyze package metadata from npm registry
4
+ */
5
+ export declare function analyzeMetadata(packageName: string): Promise<MetadataScore>;
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Analyze package metadata from npm registry
3
+ */
4
+ export async function analyzeMetadata(packageName) {
5
+ try {
6
+ // Fetch package data from npm registry
7
+ const packageData = await fetchPackageData(packageName);
8
+ const downloads = await fetchDownloadsData(packageName);
9
+ // Calculate metadata score
10
+ return calculateMetadataScore(packageData, downloads);
11
+ }
12
+ catch (error) {
13
+ // If fetching fails, return a default risky score
14
+ return createDefaultMetadataScore();
15
+ }
16
+ }
17
+ /**
18
+ * Fetch package information from npm registry
19
+ */
20
+ async function fetchPackageData(packageName) {
21
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`);
22
+ if (!response.ok) {
23
+ throw new Error(`Package not found: ${packageName}`);
24
+ }
25
+ return response.json();
26
+ }
27
+ /**
28
+ * Fetch download statistics from npm API
29
+ */
30
+ async function fetchDownloadsData(packageName) {
31
+ const response = await fetch(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(packageName)}`);
32
+ if (!response.ok) {
33
+ // No download data available, return zero
34
+ return {
35
+ downloads: 0,
36
+ start: "",
37
+ end: "",
38
+ package: packageName,
39
+ };
40
+ }
41
+ return response.json();
42
+ }
43
+ /**
44
+ * Calculate metadata risk score based on package data
45
+ */
46
+ function calculateMetadataScore(packageData, downloadsData) {
47
+ const now = new Date();
48
+ const weeklyDownloads = downloadsData.downloads;
49
+ // Get latest version publish date
50
+ const latestVersion = packageData["dist-tags"]?.latest || "";
51
+ const publishDateStr = packageData.time?.[latestVersion];
52
+ const lastPublishDate = publishDateStr ? new Date(publishDateStr) : now;
53
+ // Get package creation date (first version)
54
+ const createdDateStr = packageData.time?.created;
55
+ const createdDate = createdDateStr ? new Date(createdDateStr) : now;
56
+ // Calculate package age in days
57
+ const packageAge = Math.floor((now.getTime() - createdDate.getTime()) / (1000 * 60 * 60 * 24));
58
+ // Calculate days since last publish
59
+ const daysSincePublish = Math.floor((now.getTime() - lastPublishDate.getTime()) / (1000 * 60 * 60 * 24));
60
+ // Get maintainer info
61
+ const maintainerCount = packageData.maintainers?.length || 0;
62
+ const hasLicense = Boolean(packageData.license);
63
+ // Calculate risk score (0-10, higher = more risky)
64
+ let riskScore = 0;
65
+ // Downloads score (0-3 points)
66
+ if (weeklyDownloads < 100) {
67
+ riskScore += 3; // Very low downloads - very risky
68
+ }
69
+ else if (weeklyDownloads < 1000) {
70
+ riskScore += 2; // Low downloads - risky
71
+ }
72
+ else if (weeklyDownloads < 10000) {
73
+ riskScore += 1; // Moderate downloads - slight risk
74
+ }
75
+ // Over 10k downloads = 0 points (safe)
76
+ // Last publish date score (0-3 points)
77
+ if (daysSincePublish > 730) {
78
+ // > 2 years
79
+ riskScore += 3; // Abandoned
80
+ }
81
+ else if (daysSincePublish > 365) {
82
+ // > 1 year
83
+ riskScore += 2; // Stale
84
+ }
85
+ else if (daysSincePublish > 180) {
86
+ // > 6 months
87
+ riskScore += 1; // Moderately maintained
88
+ }
89
+ // Updated within 6 months = 0 points (well maintained)
90
+ // Package age score (0-2 points)
91
+ if (packageAge < 30) {
92
+ // Less than 1 month old
93
+ riskScore += 2; // Too new, unproven
94
+ }
95
+ else if (packageAge < 90) {
96
+ // Less than 3 months old
97
+ riskScore += 1; // Relatively new
98
+ }
99
+ // Older than 3 months = 0 points (established)
100
+ // Maintainer count score (0-1 point)
101
+ if (maintainerCount === 0) {
102
+ riskScore += 1; // No maintainers listed
103
+ }
104
+ // Has maintainers = 0 points
105
+ // License score (0-1 point)
106
+ if (!hasLicense) {
107
+ riskScore += 1; // No license
108
+ }
109
+ // Has license = 0 points
110
+ // Cap score at 10
111
+ riskScore = Math.min(riskScore, 10);
112
+ return {
113
+ version: packageData["dist-tags"]?.latest ?? "unknown",
114
+ downloads: weeklyDownloads,
115
+ lastPublishDate,
116
+ maintainerCount,
117
+ hasLicense,
118
+ packageAge,
119
+ riskScore: riskScore,
120
+ };
121
+ }
122
+ /**
123
+ * Create default metadata score for when fetching fails
124
+ */
125
+ function createDefaultMetadataScore() {
126
+ return {
127
+ version: "unknown",
128
+ downloads: 0,
129
+ lastPublishDate: new Date(),
130
+ maintainerCount: 0,
131
+ hasLicense: false,
132
+ packageAge: 0,
133
+ riskScore: 8, // High risk when we can't verify metadata
134
+ };
135
+ }
136
+ //# sourceMappingURL=metadataAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadataAnalyzer.js","sourceRoot":"","sources":["../../src/scanner/metadataAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ScriptRisk } from "../types.js";
2
+ /**
3
+ * Analyze package.json scripts for security risks
4
+ */
5
+ export declare function analyzeScripts(packageName: string): Promise<ScriptRisk>;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Dangerous commands that are red flags in package scripts
3
+ */
4
+ const DANGEROUS_COMMANDS = [
5
+ "curl",
6
+ "wget",
7
+ "eval",
8
+ "chmod",
9
+ "chown",
10
+ "sudo",
11
+ "rm -rf",
12
+ "dd if=",
13
+ "mkfs",
14
+ ":(){ :|:& };:", // Fork bomb
15
+ "/dev/sda",
16
+ "/dev/null",
17
+ ">/dev/",
18
+ "format c:",
19
+ ];
20
+ /**
21
+ * Suspicious commands that warrant investigation
22
+ */
23
+ const SUSPICIOUS_COMMANDS = [
24
+ "nc ", // netcat
25
+ "telnet",
26
+ "ssh",
27
+ "scp",
28
+ "ftp",
29
+ "base64",
30
+ "exec",
31
+ "child_process",
32
+ "execSync",
33
+ "spawn",
34
+ ".decrypt",
35
+ "crypto",
36
+ ];
37
+ /**
38
+ * Network-related commands
39
+ */
40
+ const NETWORK_COMMANDS = [
41
+ "http://",
42
+ "https://",
43
+ "fetch(",
44
+ "axios",
45
+ "request(",
46
+ "download",
47
+ ];
48
+ /**
49
+ * Lifecycle hooks that run automatically
50
+ */
51
+ const LIFECYCLE_HOOKS = [
52
+ "preinstall",
53
+ "install",
54
+ "postinstall",
55
+ "preuninstall",
56
+ "uninstall",
57
+ "postuninstall",
58
+ "preversion",
59
+ "version",
60
+ "postversion",
61
+ ];
62
+ /**
63
+ * Analyze package.json scripts for security risks
64
+ */
65
+ export async function analyzeScripts(packageName) {
66
+ try {
67
+ // Fetch package.json from npm registry
68
+ const packageJson = await fetchPackageJson(packageName);
69
+ if (!packageJson.scripts) {
70
+ // No scripts = safe
71
+ return createSafeScriptResult();
72
+ }
73
+ // Analyze the scripts
74
+ return analyzePackageScripts(packageJson.scripts);
75
+ }
76
+ catch (error) {
77
+ // If fetching fails, assume safe (no scripts to analyze)
78
+ return createSafeScriptResult();
79
+ }
80
+ }
81
+ /**
82
+ * Fetch package.json from npm registry
83
+ */
84
+ async function fetchPackageJson(packageName) {
85
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`);
86
+ if (!response.ok) {
87
+ throw new Error(`Package not found: ${packageName}`);
88
+ }
89
+ return response.json();
90
+ }
91
+ /**
92
+ * Analyze scripts object for suspicious patterns
93
+ */
94
+ function analyzePackageScripts(scripts) {
95
+ const suspiciousScripts = [];
96
+ const dangerousCommands = [];
97
+ let riskScore = 0;
98
+ // Check each script
99
+ for (const [scriptName, scriptContent] of Object.entries(scripts)) {
100
+ const analysis = analyzeScript(scriptName, scriptContent);
101
+ if (analysis.isDangerous) {
102
+ suspiciousScripts.push(`${scriptName}: ${analysis.reason || "dangerous command"}`);
103
+ dangerousCommands.push(...analysis.commands);
104
+ riskScore += analysis.riskPoints;
105
+ }
106
+ }
107
+ // Check for automatic lifecycle hooks
108
+ const hasLifecycleHooks = LIFECYCLE_HOOKS.some((hook) => Object.keys(scripts).includes(hook));
109
+ if (hasLifecycleHooks) {
110
+ const lifecycleScripts = LIFECYCLE_HOOKS.filter((hook) => Object.keys(scripts).includes(hook));
111
+ suspiciousScripts.push(`Automatic lifecycle hooks: ${lifecycleScripts.join(", ")}`);
112
+ riskScore += 2; // Additional risk for automatic execution
113
+ }
114
+ // Cap the score at 10
115
+ riskScore = Math.min(riskScore, 10);
116
+ const hasSuspiciousScripts = suspiciousScripts.length > 0;
117
+ return {
118
+ hasSuspiciousScripts,
119
+ suspiciousScripts,
120
+ dangerousCommands: [...new Set(dangerousCommands)], // Remove duplicates
121
+ riskScore: riskScore,
122
+ };
123
+ }
124
+ /**
125
+ * Analyze individual script for suspicious patterns
126
+ */
127
+ function analyzeScript(scriptName, scriptContent) {
128
+ const lowerContent = scriptContent.toLowerCase();
129
+ const foundCommands = [];
130
+ let riskPoints = 0;
131
+ let reason = "";
132
+ // Check for dangerous commands
133
+ for (const cmd of DANGEROUS_COMMANDS) {
134
+ if (lowerContent.includes(cmd.toLowerCase())) {
135
+ foundCommands.push(cmd);
136
+ riskPoints += 5; // Very high risk
137
+ reason = `dangerous command: ${cmd}`;
138
+ }
139
+ }
140
+ // Check for suspicious commands
141
+ for (const cmd of SUSPICIOUS_COMMANDS) {
142
+ if (lowerContent.includes(cmd.toLowerCase())) {
143
+ foundCommands.push(cmd);
144
+ riskPoints += 2; // Medium risk
145
+ if (!reason)
146
+ reason = `suspicious command: ${cmd}`;
147
+ }
148
+ }
149
+ // Check for network commands
150
+ for (const cmd of NETWORK_COMMANDS) {
151
+ if (lowerContent.includes(cmd.toLowerCase())) {
152
+ foundCommands.push(cmd);
153
+ riskPoints += 1; // Low risk (network calls are common)
154
+ if (!reason)
155
+ reason = `network activity: ${cmd}`;
156
+ }
157
+ }
158
+ // Check for obfuscated code patterns
159
+ if (lowerContent.includes("\\x") ||
160
+ lowerContent.includes("\\u") ||
161
+ lowerContent.match(/[a-z0-9]{50,}/) // Long random strings
162
+ ) {
163
+ foundCommands.push("obfuscated code");
164
+ riskPoints += 3;
165
+ if (!reason)
166
+ reason = "potentially obfuscated code";
167
+ }
168
+ const isDangerous = foundCommands.length > 0;
169
+ return {
170
+ isDangerous,
171
+ reason,
172
+ commands: foundCommands,
173
+ riskPoints,
174
+ };
175
+ }
176
+ /**
177
+ * Create a safe script result (no suspicious scripts found)
178
+ */
179
+ function createSafeScriptResult() {
180
+ return {
181
+ hasSuspiciousScripts: false,
182
+ suspiciousScripts: [],
183
+ dangerousCommands: [],
184
+ riskScore: 0,
185
+ };
186
+ }
187
+ //# sourceMappingURL=scriptAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scriptAnalyzer.js","sourceRoot":"","sources":["../../src/scanner/scriptAnalyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export {};
2
+ // Batch package analyzer
3
+ // Will be implemented in Phase 5
4
+ //# sourceMappingURL=batchAnalyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchAnalyze.js","sourceRoot":"","sources":["../../src/scanner-project/batchAnalyze.ts"],"names":[],"mappings":";AAAA,yBAAyB;AACzB,iCAAiC"}
@@ -0,0 +1,4 @@
1
+ export * from "./readDependencies.js";
2
+ export * from "./scanProject.js";
3
+ export * from "./scanNodeModules.js";
4
+ export * from "./batchAnalyze.js";
@@ -0,0 +1,6 @@
1
+ // Project scanner barrel exports
2
+ export * from "./readDependencies.js";
3
+ export * from "./scanProject.js";
4
+ export * from "./scanNodeModules.js";
5
+ export * from "./batchAnalyze.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner-project/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { DependencyList } from "../types.js";
2
+ /**
3
+ * Read dependencies from package.json in the project
4
+ */
5
+ export declare function readDependencies(cwd: string): DependencyList;