npm-scan-plus 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.
- package/.eslintrc.json +32 -0
- package/.github/CODEOWNERS +3 -0
- package/.github/workflows/ci.yml +105 -0
- package/.prettierrc +10 -0
- package/FUNDING.yml +1 -0
- package/PLAN.md +151 -0
- package/README.md +150 -0
- package/bin/npm-scan +13 -0
- package/bin/npm-scan-wrap +100 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +299 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/lib/blocklist.d.ts +45 -0
- package/dist/lib/blocklist.d.ts.map +1 -0
- package/dist/lib/blocklist.js +256 -0
- package/dist/lib/blocklist.js.map +1 -0
- package/dist/lib/extended.js +314 -0
- package/dist/lib/extended.js.map +1 -0
- package/dist/lib/integrity.js +247 -0
- package/dist/lib/integrity.js.map +1 -0
- package/dist/lib/patterns.d.ts +76 -0
- package/dist/lib/patterns.d.ts.map +1 -0
- package/dist/lib/patterns.js +414 -0
- package/dist/lib/patterns.js.map +1 -0
- package/dist/lib/registry.d.ts +42 -0
- package/dist/lib/registry.d.ts.map +1 -0
- package/dist/lib/registry.js +157 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/lib/scanner.d.ts +43 -0
- package/dist/lib/scanner.d.ts.map +1 -0
- package/dist/lib/scanner.js +432 -0
- package/dist/lib/scanner.js.map +1 -0
- package/dist/lib/vuln.js +284 -0
- package/dist/lib/vuln.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +18 -0
- package/package.json +56 -0
- package/src/cli/index.ts +336 -0
- package/src/lib/blocklist.ts +239 -0
- package/src/lib/extended.ts +384 -0
- package/src/lib/integrity.ts +253 -0
- package/src/lib/patterns.ts +404 -0
- package/src/lib/registry.ts +146 -0
- package/src/lib/scanner.ts +447 -0
- package/src/lib/vuln.ts +321 -0
- package/src/types.ts +102 -0
- package/tests/blocklist.test.ts +89 -0
- package/tests/extended.test.ts +204 -0
- package/tests/patterns.test.ts +147 -0
- package/tests/scanner.test.ts +116 -0
- package/tests/vuln.test.ts +66 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Detection patterns for malicious code, obfuscation, and suspicious behavior
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.CODE_EXTENSIONS = exports.SENSITIVE_FILES = exports.SUSPICIOUS_SCRIPTS = exports.SUSPICIOUS_PATTERNS = exports.OBFUSCATION_PATTERNS = void 0;
|
|
40
|
+
exports.scanFile = scanFile;
|
|
41
|
+
exports.scanPackageJsonScripts = scanPackageJsonScripts;
|
|
42
|
+
exports.scanDirectory = scanDirectory;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
// Patterns that indicate obfuscated code
|
|
46
|
+
const OBFUSCATION_PATTERNS = [
|
|
47
|
+
{
|
|
48
|
+
pattern: /eval\s*\(\s*(?:atob|fromCharCode|String\.fromCharCode)/gi,
|
|
49
|
+
type: 'obfuscation',
|
|
50
|
+
severity: 'high',
|
|
51
|
+
message: 'eval() with character code decoding - common obfuscation technique'
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
pattern: /eval\s*\(\s*["'`]([A-Za-z0-9+\/=]{100,})["'`]*/gi,
|
|
55
|
+
type: 'obfuscation',
|
|
56
|
+
severity: 'high',
|
|
57
|
+
message: 'eval() with base64-encoded string'
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pattern: /new\s+Function\s*\(\s*(?:atob|fromCharCode)/gi,
|
|
61
|
+
type: 'obfuscation',
|
|
62
|
+
severity: 'high',
|
|
63
|
+
message: 'Dynamic Function with character code decoding'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pattern: /\\x([0-9a-fA-F]{2})/g,
|
|
67
|
+
type: 'obfuscation',
|
|
68
|
+
severity: 'medium',
|
|
69
|
+
message: 'Hex-encoded characters in code'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
pattern: /\\u([0-9a-fA-F]{4})/g,
|
|
73
|
+
type: 'obfuscation',
|
|
74
|
+
severity: 'medium',
|
|
75
|
+
message: 'Unicode-escaped characters in code'
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
pattern: /(?:atob|btoa)\s*\([^)]*\)/g,
|
|
79
|
+
type: 'obfuscation',
|
|
80
|
+
severity: 'medium',
|
|
81
|
+
message: 'Base64 encoding/decoding functions detected'
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
pattern: /String\.fromCharCode\((?:\s*\d+\s*,?)+\)/g,
|
|
85
|
+
type: 'obfuscation',
|
|
86
|
+
severity: 'medium',
|
|
87
|
+
message: 'String.fromCharCode() to hide code'
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
pattern: /\$_\s*=\s*["'`]/g,
|
|
91
|
+
type: 'obfuscation',
|
|
92
|
+
severity: 'low',
|
|
93
|
+
message: 'Unusual variable naming pattern'
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
exports.OBFUSCATION_PATTERNS = OBFUSCATION_PATTERNS;
|
|
97
|
+
// Patterns that indicate malicious/malware behavior
|
|
98
|
+
const SUSPICIOUS_PATTERNS = [
|
|
99
|
+
{
|
|
100
|
+
pattern: /(?:process\.env|process)\s*\.\s*(?:env|argv)\s*\[.*?(?:KEY|SECRET|TOKEN|PASS|Auth|Credential)/gi,
|
|
101
|
+
type: 'suspicious_code',
|
|
102
|
+
severity: 'critical',
|
|
103
|
+
message: 'Accessing environment variables with sensitive keywords'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
pattern: /fetch\s*\(\s*["'](?:https?:)?\/\/(?:[0-9]{1,3}\.){3}[0-9]{1,3}/gi,
|
|
107
|
+
type: 'suspicious_code',
|
|
108
|
+
severity: 'high',
|
|
109
|
+
message: 'Network request to IP address (bypasses DNS)'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
pattern: /https?:\/\/(?:pastebin|hastebin|ipfs\.io|cloudflare|workers\.dev)\.\w+/gi,
|
|
113
|
+
type: 'suspicious_code',
|
|
114
|
+
severity: 'high',
|
|
115
|
+
message: 'Network request to external code hosting service'
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
pattern: /child_process\s*\.\s*(?:exec|spawn|sync)\s*\(\s*["'`]/gi,
|
|
119
|
+
type: 'suspicious_code',
|
|
120
|
+
severity: 'high',
|
|
121
|
+
message: 'Executing shell commands from package code'
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
pattern: /net\.connect\(|require\s*\(\s*["'](?:net|http|tls|crypto)["']\s*\)/gi,
|
|
125
|
+
type: 'suspicious_code',
|
|
126
|
+
severity: 'medium',
|
|
127
|
+
message: 'Network or crypto module required'
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
pattern: /require\s*\(\s*["'](?:child_process|exec|spawn)["']\s*\)/gi,
|
|
131
|
+
type: 'suspicious_code',
|
|
132
|
+
severity: 'high',
|
|
133
|
+
message: 'child_process module required - potential command execution'
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
pattern: /setTimeout\s*\(\s*["'`]/gi,
|
|
137
|
+
type: 'suspicious_code',
|
|
138
|
+
severity: 'low',
|
|
139
|
+
message: 'Delayed code execution'
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
pattern: /setInterval\s*\(\s*["'`]/gi,
|
|
143
|
+
type: 'suspicious_code',
|
|
144
|
+
severity: 'low',
|
|
145
|
+
message: 'Repeating scheduled code execution'
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
pattern: /\.exec\s*\(|child_process\.\s*exec/gi,
|
|
149
|
+
type: 'suspicious_code',
|
|
150
|
+
severity: 'high',
|
|
151
|
+
message: 'Shell command execution'
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
pattern: /fs\s*\.\s*(?:readFile|writeFile|appendFile|readFileSync|writeFileSync)\s*\(\s*(?:__dirname|process\.cwd\(\))/gi,
|
|
155
|
+
type: 'suspicious_code',
|
|
156
|
+
severity: 'medium',
|
|
157
|
+
message: 'File system access in package root'
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
pattern: /(?:readdirSync|readdir|readFileSync|readlinkSync)\s*\(\s*(?:\.|process\.cwd)/gi,
|
|
161
|
+
type: 'suspicious_code',
|
|
162
|
+
severity: 'medium',
|
|
163
|
+
message: 'Scanning directories outside package'
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
pattern: /eval\s*\(\s*process\.env/gi,
|
|
167
|
+
type: 'suspicious_code',
|
|
168
|
+
severity: 'critical',
|
|
169
|
+
message: 'Evaluating environment variables'
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
pattern: /require\s*\(\s*["'](?:https?|http)["']\s*\)/gi,
|
|
173
|
+
type: 'suspicious_code',
|
|
174
|
+
severity: 'medium',
|
|
175
|
+
message: 'HTTP/HTTPS module required'
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
pattern: /crypto\s*\.\s*createHash\s*\(\s*["'](?:sha|md5)["']\s*\)/gi,
|
|
179
|
+
type: 'suspicious_code',
|
|
180
|
+
severity: 'low',
|
|
181
|
+
message: 'Cryptographic hashing'
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
// Crypto mining patterns
|
|
185
|
+
pattern: /(?:stratum\+tcp|stratum\.bitcoin|cgminer|antminer|cryptonight)/gi,
|
|
186
|
+
type: 'suspicious_code',
|
|
187
|
+
severity: 'critical',
|
|
188
|
+
message: 'Crypto mining pool connection detected'
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
// Keylogging patterns
|
|
192
|
+
pattern: /(?:addEventListener\s*\(\s*["'](?:keydown|keypress|keyup)|onkey)/gi,
|
|
193
|
+
type: 'suspicious_code',
|
|
194
|
+
severity: 'high',
|
|
195
|
+
message: 'Keyboard event listener - potential keylogger'
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
pattern: /(?:key|code)\s*:\s*(?:\d{1,3}\s*,?\s*){3,}/gi,
|
|
199
|
+
type: 'suspicious_code',
|
|
200
|
+
severity: 'high',
|
|
201
|
+
message: 'Potential keyboard scanning code'
|
|
202
|
+
}
|
|
203
|
+
];
|
|
204
|
+
exports.SUSPICIOUS_PATTERNS = SUSPICIOUS_PATTERNS;
|
|
205
|
+
// Suspicious lifecycle scripts in package.json
|
|
206
|
+
const SUSPICIOUS_SCRIPTS = [
|
|
207
|
+
{
|
|
208
|
+
script: 'postinstall',
|
|
209
|
+
severity: 'high',
|
|
210
|
+
message: 'postinstall script executes automatically after install'
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
script: 'preinstall',
|
|
214
|
+
severity: 'medium',
|
|
215
|
+
message: 'preinstall script runs before package installs'
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
script: 'postpublish',
|
|
219
|
+
severity: 'medium',
|
|
220
|
+
message: 'postpublish script runs after package is published'
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
script: 'preuninstall',
|
|
224
|
+
severity: 'low',
|
|
225
|
+
message: 'preuninstall script runs before uninstall'
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
script: 'postuninstall',
|
|
229
|
+
severity: 'medium',
|
|
230
|
+
message: 'postuninstall script runs after uninstall'
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
script: 'preversion',
|
|
234
|
+
severity: 'low',
|
|
235
|
+
message: 'preversion script runs before version bump'
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
script: 'postversion',
|
|
239
|
+
severity: 'low',
|
|
240
|
+
message: 'postversion script runs after version bump'
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
script: 'prepack',
|
|
244
|
+
severity: 'low',
|
|
245
|
+
message: 'prepack script runs before packing'
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
script: 'postpack',
|
|
249
|
+
severity: 'low',
|
|
250
|
+
message: 'postpack script runs after packing'
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
script: 'prepare',
|
|
254
|
+
severity: 'low',
|
|
255
|
+
message: 'prepare script runs on install and publish'
|
|
256
|
+
}
|
|
257
|
+
];
|
|
258
|
+
exports.SUSPICIOUS_SCRIPTS = SUSPICIOUS_SCRIPTS;
|
|
259
|
+
// Sensitive files that should not be in packages
|
|
260
|
+
const SENSITIVE_FILES = [
|
|
261
|
+
/\.env$/,
|
|
262
|
+
/\.env\.[a-z]+$/,
|
|
263
|
+
/\.git\/config$/,
|
|
264
|
+
/\.aws\/credentials$/,
|
|
265
|
+
/\.ssh\/id_.*$/,
|
|
266
|
+
/credentials\.json$/,
|
|
267
|
+
/\.npmrc$/,
|
|
268
|
+
/\.htpasswd$/,
|
|
269
|
+
/secrets\.ya?ml$/,
|
|
270
|
+
/\.pem$/,
|
|
271
|
+
/\.key$/,
|
|
272
|
+
/\.p12$/,
|
|
273
|
+
/\.pfx$/,
|
|
274
|
+
/id_rsa/,
|
|
275
|
+
/id_dsa/,
|
|
276
|
+
/\.bash_history$/,
|
|
277
|
+
/\.zsh_history$/,
|
|
278
|
+
/\.history$/,
|
|
279
|
+
/_history$/,
|
|
280
|
+
/\.sql$/,
|
|
281
|
+
/\.db$/
|
|
282
|
+
];
|
|
283
|
+
exports.SENSITIVE_FILES = SENSITIVE_FILES;
|
|
284
|
+
// File extensions that might contain executable code
|
|
285
|
+
const CODE_EXTENSIONS = [
|
|
286
|
+
'.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx',
|
|
287
|
+
'.py', '.rb', '.php', '.pl', '.sh', '.bash',
|
|
288
|
+
'.exe', '.dll', '.so', '.dylib', '.bin',
|
|
289
|
+
'.wasm', '.class', '.jar'
|
|
290
|
+
];
|
|
291
|
+
exports.CODE_EXTENSIONS = CODE_EXTENSIONS;
|
|
292
|
+
/**
|
|
293
|
+
* Scan a single file for suspicious patterns
|
|
294
|
+
*/
|
|
295
|
+
function scanFile(filePath, content) {
|
|
296
|
+
const threats = [];
|
|
297
|
+
const fileName = path.basename(filePath);
|
|
298
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
299
|
+
// Skip node_modules packages themselves
|
|
300
|
+
if (filePath.includes('node_modules/')) {
|
|
301
|
+
return [];
|
|
302
|
+
}
|
|
303
|
+
// Check for obfuscation patterns
|
|
304
|
+
for (const { pattern, type, severity, message } of OBFUSCATION_PATTERNS) {
|
|
305
|
+
const matches = content.match(pattern);
|
|
306
|
+
if (matches) {
|
|
307
|
+
threats.push({
|
|
308
|
+
package: 'scanning',
|
|
309
|
+
file: fileName,
|
|
310
|
+
type,
|
|
311
|
+
severity,
|
|
312
|
+
message,
|
|
313
|
+
code: matches[0].substring(0, 100)
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Check for suspicious patterns (only in code files)
|
|
318
|
+
if (CODE_EXTENSIONS.includes(ext)) {
|
|
319
|
+
for (const { pattern, type, severity, message } of SUSPICIOUS_PATTERNS) {
|
|
320
|
+
const matches = content.match(pattern);
|
|
321
|
+
if (matches) {
|
|
322
|
+
threats.push({
|
|
323
|
+
package: 'scanning',
|
|
324
|
+
file: fileName,
|
|
325
|
+
type,
|
|
326
|
+
severity,
|
|
327
|
+
message,
|
|
328
|
+
code: matches[0].substring(0, 100)
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// Check for sensitive files
|
|
334
|
+
for (const pattern of SENSITIVE_FILES) {
|
|
335
|
+
if (pattern.test(fileName)) {
|
|
336
|
+
threats.push({
|
|
337
|
+
package: 'scanning',
|
|
338
|
+
file: fileName,
|
|
339
|
+
type: 'suspicious_code',
|
|
340
|
+
severity: 'high',
|
|
341
|
+
message: `Sensitive file detected in package: ${fileName}`
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return threats;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Check package.json scripts for suspicious behavior
|
|
349
|
+
*/
|
|
350
|
+
function scanPackageJsonScripts(scripts) {
|
|
351
|
+
const threats = [];
|
|
352
|
+
if (!scripts)
|
|
353
|
+
return threats;
|
|
354
|
+
for (const [scriptName, scriptContent] of Object.entries(scripts)) {
|
|
355
|
+
const scriptDef = SUSPICIOUS_SCRIPTS.find(s => s.script === scriptName);
|
|
356
|
+
if (scriptDef) {
|
|
357
|
+
// Check if script content is suspicious
|
|
358
|
+
const isSuspicious = /curl|wget|npm|node|yarn|python|perl|bash|sh|\||&&|\$\(|;/.test(scriptContent) ||
|
|
359
|
+
scriptContent.length > 200;
|
|
360
|
+
threats.push({
|
|
361
|
+
package: 'scanning',
|
|
362
|
+
file: 'package.json',
|
|
363
|
+
type: isSuspicious ? 'suspicious_script' : 'supply_chain',
|
|
364
|
+
severity: isSuspicious ? scriptDef.severity : 'low',
|
|
365
|
+
message: `${scriptDef.message}: "${scriptName}"`,
|
|
366
|
+
code: scriptContent.substring(0, 100)
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return threats;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Scan directory for all files
|
|
374
|
+
*/
|
|
375
|
+
function scanDirectory(dirPath, extensions) {
|
|
376
|
+
const files = new Map();
|
|
377
|
+
const codeExtensions = extensions || CODE_EXTENSIONS;
|
|
378
|
+
function walkDir(dir, basePath = '') {
|
|
379
|
+
try {
|
|
380
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
381
|
+
for (const entry of entries) {
|
|
382
|
+
const fullPath = path.join(dir, entry.name);
|
|
383
|
+
const relativePath = path.join(basePath, entry.name);
|
|
384
|
+
if (entry.isDirectory()) {
|
|
385
|
+
// Skip certain directories
|
|
386
|
+
if (['node_modules', '.git', 'test', '__tests__', 'coverage'].includes(entry.name)) {
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
walkDir(fullPath, relativePath);
|
|
390
|
+
}
|
|
391
|
+
else if (entry.isFile()) {
|
|
392
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
393
|
+
if (codeExtensions.includes(ext)) {
|
|
394
|
+
try {
|
|
395
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
396
|
+
if (content.length < 1_000_000) { // Skip files > 1MB
|
|
397
|
+
files.set(relativePath, content);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch (e) {
|
|
401
|
+
// Skip binary or unreadable files
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
catch (e) {
|
|
408
|
+
// Skip inaccessible directories
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
walkDir(dirPath);
|
|
412
|
+
return files;
|
|
413
|
+
}
|
|
414
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/lib/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm registry API client
|
|
3
|
+
* Fetches package metadata and tarballs from npm registry
|
|
4
|
+
*/
|
|
5
|
+
import type { PackageMetadata, ScanOptions } from './types';
|
|
6
|
+
export declare class RegistryClient {
|
|
7
|
+
private registry;
|
|
8
|
+
private cache;
|
|
9
|
+
constructor(options?: {
|
|
10
|
+
registry?: string;
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Fetch package metadata from npm registry
|
|
14
|
+
*/
|
|
15
|
+
getPackageMetadata(packageName: string, version?: string): Promise<PackageMetadata>;
|
|
16
|
+
/**
|
|
17
|
+
* Normalize npm registry response to our PackageMetadata type
|
|
18
|
+
*/
|
|
19
|
+
private normalizeMetadata;
|
|
20
|
+
/**
|
|
21
|
+
* Download and extract package tarball to temp directory
|
|
22
|
+
*/
|
|
23
|
+
downloadPackage(packageName: string, version?: string): Promise<{
|
|
24
|
+
tempDir: string;
|
|
25
|
+
files: string[];
|
|
26
|
+
integrity: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Recursively get all files in directory
|
|
30
|
+
*/
|
|
31
|
+
private getAllFiles;
|
|
32
|
+
/**
|
|
33
|
+
* Clean up temp directory
|
|
34
|
+
*/
|
|
35
|
+
cleanup(tempDir: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get all available versions of a package
|
|
38
|
+
*/
|
|
39
|
+
getVersions(packageName: string): Promise<string[]>;
|
|
40
|
+
}
|
|
41
|
+
export declare function createRegistryClient(options?: ScanOptions): RegistryClient;
|
|
42
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI5D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAA2C;gBAE5C,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAI3C;;OAEG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA6BzF;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAwBzB;;OAEG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QACpE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IA2CF;;OAEG;IACH,OAAO,CAAC,WAAW;IAoBnB;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ9B;;OAEG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAS1D;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,cAAc,CAE1E"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* npm registry API client
|
|
4
|
+
* Fetches package metadata and tarballs from npm registry using native fetch
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.RegistryClient = void 0;
|
|
41
|
+
exports.createRegistryClient = createRegistryClient;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const os = __importStar(require("os"));
|
|
45
|
+
const tar = __importStar(require("tar"));
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
|
|
48
|
+
class RegistryClient {
|
|
49
|
+
registry;
|
|
50
|
+
cache = new Map();
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.registry = options?.registry || DEFAULT_REGISTRY;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Fetch package metadata from npm registry
|
|
56
|
+
*/
|
|
57
|
+
async getPackageMetadata(packageName, version) {
|
|
58
|
+
const cacheKey = `${packageName}@${version || 'latest'}`;
|
|
59
|
+
if (this.cache.has(cacheKey)) {
|
|
60
|
+
return this.cache.get(cacheKey);
|
|
61
|
+
}
|
|
62
|
+
const url = `${this.registry}/${packageName}${version ? `/${version}` : ''}`;
|
|
63
|
+
try {
|
|
64
|
+
const response = await fetch(url);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
if (response.status === 404) {
|
|
67
|
+
throw new Error(`Package not found: ${packageName}`);
|
|
68
|
+
}
|
|
69
|
+
throw new Error(`Failed to fetch ${packageName}: ${response.statusText}`);
|
|
70
|
+
}
|
|
71
|
+
const data = await response.json();
|
|
72
|
+
this.cache.set(cacheKey, data);
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Failed to fetch ${packageName}: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Download and extract package tarball to temp directory
|
|
81
|
+
*/
|
|
82
|
+
async downloadPackage(packageName, version) {
|
|
83
|
+
const metadata = await this.getPackageMetadata(packageName, version);
|
|
84
|
+
const dist = metadata.dist || {};
|
|
85
|
+
if (!dist.tarball) {
|
|
86
|
+
throw new Error(`No tarball found for ${packageName}`);
|
|
87
|
+
}
|
|
88
|
+
const tempDir = path.join(os.tmpdir(), `npm-scan-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`);
|
|
89
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
90
|
+
const tarballPath = path.join(tempDir, 'package.tgz');
|
|
91
|
+
// Download tarball
|
|
92
|
+
const response = await fetch(dist.tarball);
|
|
93
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
94
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
95
|
+
fs.writeFileSync(tarballPath, buffer);
|
|
96
|
+
// Calculate integrity hash (sha512)
|
|
97
|
+
const integrity = 'sha512-' + crypto.createHash('sha512').update(buffer).digest('base64');
|
|
98
|
+
// Extract tarball
|
|
99
|
+
const extractDir = path.join(tempDir, 'package');
|
|
100
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
101
|
+
await tar.extract({
|
|
102
|
+
file: tarballPath,
|
|
103
|
+
cwd: extractDir
|
|
104
|
+
});
|
|
105
|
+
// Get list of extracted files
|
|
106
|
+
const files = this.getAllFiles(extractDir);
|
|
107
|
+
return { tempDir, files, integrity };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Recursively get all files in directory
|
|
111
|
+
*/
|
|
112
|
+
getAllFiles(dir, baseDir) {
|
|
113
|
+
const files = [];
|
|
114
|
+
const base = baseDir || dir;
|
|
115
|
+
try {
|
|
116
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
const fullPath = path.join(dir, entry.name);
|
|
119
|
+
const relativePath = path.relative(base, fullPath);
|
|
120
|
+
if (entry.isDirectory()) {
|
|
121
|
+
files.push(...this.getAllFiles(fullPath, base));
|
|
122
|
+
}
|
|
123
|
+
else if (entry.isFile()) {
|
|
124
|
+
files.push(relativePath);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
// Skip inaccessible
|
|
130
|
+
}
|
|
131
|
+
return files;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Clean up temp directory
|
|
135
|
+
*/
|
|
136
|
+
cleanup(tempDir) {
|
|
137
|
+
try {
|
|
138
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
// Ignore cleanup errors
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get all available versions of a package
|
|
146
|
+
*/
|
|
147
|
+
async getVersions(packageName) {
|
|
148
|
+
const response = await fetch(`${this.registry}/${packageName}`);
|
|
149
|
+
const data = await response.json();
|
|
150
|
+
return Object.keys(data.versions || {}).sort();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.RegistryClient = RegistryClient;
|
|
154
|
+
function createRegistryClient(options) {
|
|
155
|
+
return new RegistryClient({ registry: options?.registry });
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4IH,oDAEC;AA5ID,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,yCAA2B;AAC3B,+CAAiC;AAEjC,MAAM,gBAAgB,GAAG,4BAA4B,CAAC;AAEtD,MAAa,cAAc;IACjB,QAAQ,CAAS;IACjB,KAAK,GAAQ,IAAI,GAAG,EAAE,CAAC;IAE/B,YAAY,OAA+B;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,gBAAgB,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,OAAgB;QAC5D,MAAM,QAAQ,GAAG,GAAG,WAAW,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;QAEzD,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAE7E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,mBAAmB,WAAW,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5E,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,WAAW,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,OAAgB;QAKzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,YAAY,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5G,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEtD,mBAAmB;QACnB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAEtC,oCAAoC;QACpC,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE1F,kBAAkB;QAClB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACjD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,MAAM,GAAG,CAAC,OAAO,CAAC;YAChB,IAAI,EAAE,WAAW;YACjB,GAAG,EAAE,UAAU;SAChB,CAAC,CAAC;QAEH,8BAA8B;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAE3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,GAAW,EAAE,OAAgB;QAC/C,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;QAE5B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBAEnD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;gBAClD,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC1B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,oBAAoB;QACtB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,OAAe;QACrB,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,WAAmB;QACnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,CAAC;CACF;AAhID,wCAgIC;AAED,SAAgB,oBAAoB,CAAC,OAAa;IAChD,OAAO,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core scanner module
|
|
3
|
+
* Pre and post-install security scanning for npm packages
|
|
4
|
+
*/
|
|
5
|
+
import type { ScanResult, ScanOptions, PostInstallScanResult } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Main scanner class
|
|
8
|
+
*/
|
|
9
|
+
export declare class Scanner {
|
|
10
|
+
private registry;
|
|
11
|
+
private options;
|
|
12
|
+
constructor(options?: ScanOptions);
|
|
13
|
+
/**
|
|
14
|
+
* Pre-install scan: Check a package before installation
|
|
15
|
+
*/
|
|
16
|
+
preInstallScan(packageName: string, version?: string): Promise<ScanResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Post-install scan: Scan downloaded packages
|
|
19
|
+
*/
|
|
20
|
+
postInstallScan(folderPath?: string): Promise<PostInstallScanResult>;
|
|
21
|
+
/**
|
|
22
|
+
* Full scan: Pre-scan, then install, then post-scan
|
|
23
|
+
*/
|
|
24
|
+
fullScan(packageName: string, version?: string, folderPath?: string): Promise<{
|
|
25
|
+
pre: ScanResult;
|
|
26
|
+
post: PostInstallScanResult;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Find all packages in node_modules
|
|
30
|
+
*/
|
|
31
|
+
private findPackages;
|
|
32
|
+
/**
|
|
33
|
+
* Determine overall status from threats and score
|
|
34
|
+
*/
|
|
35
|
+
private determineStatus;
|
|
36
|
+
}
|
|
37
|
+
export declare function createScanner(options?: ScanOptions): Scanner;
|
|
38
|
+
declare const _default: {
|
|
39
|
+
Scanner: typeof Scanner;
|
|
40
|
+
createScanner: typeof createScanner;
|
|
41
|
+
};
|
|
42
|
+
export default _default;
|
|
43
|
+
//# sourceMappingURL=scanner.d.ts.map
|