@triedotdev/mcp 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/QUICK_START.md +230 -0
- package/README.md +235 -0
- package/dist/chunk-3CS6Z2SL.js +927 -0
- package/dist/chunk-3CS6Z2SL.js.map +1 -0
- package/dist/chunk-6NLHFIYA.js +344 -0
- package/dist/chunk-6NLHFIYA.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-E7CKHS3R.js +7615 -0
- package/dist/chunk-E7CKHS3R.js.map +1 -0
- package/dist/chunk-EYNAGEQK.js +950 -0
- package/dist/chunk-EYNAGEQK.js.map +1 -0
- package/dist/chunk-MR755QGT.js +927 -0
- package/dist/chunk-MR755QGT.js.map +1 -0
- package/dist/cli/create-agent.d.ts +1 -0
- package/dist/cli/create-agent.js +156 -0
- package/dist/cli/create-agent.js.map +1 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +280 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/yolo-daemon.d.ts +1 -0
- package/dist/cli/yolo-daemon.js +326 -0
- package/dist/cli/yolo-daemon.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3882 -0
- package/dist/index.js.map +1 -0
- package/dist/vibe-code-signatures-4CBHUSI7.js +15 -0
- package/dist/vibe-code-signatures-4CBHUSI7.js.map +1 -0
- package/dist/vulnerability-signatures-J3CUQ7VR.js +17 -0
- package/dist/vulnerability-signatures-J3CUQ7VR.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,927 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AhoCorasick
|
|
3
|
+
} from "./chunk-6NLHFIYA.js";
|
|
4
|
+
|
|
5
|
+
// src/trie/vulnerability-signatures.ts
|
|
6
|
+
var ALWAYS_EXCLUDED_FILES = [
|
|
7
|
+
/vulnerability-signatures\.[jt]s$/,
|
|
8
|
+
// CRITICAL: Never scan ourselves!
|
|
9
|
+
/vibe-code-signatures\.[jt]s$/,
|
|
10
|
+
// Never scan signature files
|
|
11
|
+
/package-lock\.json$/,
|
|
12
|
+
// Lock files
|
|
13
|
+
/yarn\.lock$/,
|
|
14
|
+
/pnpm-lock\.yaml$/,
|
|
15
|
+
/node_modules\//,
|
|
16
|
+
// Dependencies
|
|
17
|
+
/\.d\.ts$/,
|
|
18
|
+
// Type definitions
|
|
19
|
+
/\.min\.[jt]s$/,
|
|
20
|
+
// Minified files
|
|
21
|
+
/dist\//,
|
|
22
|
+
// Build output
|
|
23
|
+
/build\//
|
|
24
|
+
];
|
|
25
|
+
var EXCLUDED_FILE_PATTERNS = [
|
|
26
|
+
/\.test\.[jt]sx?$/,
|
|
27
|
+
// Test files
|
|
28
|
+
/\.spec\.[jt]sx?$/,
|
|
29
|
+
// Spec files
|
|
30
|
+
/__tests__\//,
|
|
31
|
+
// Test directories
|
|
32
|
+
/\/test\//,
|
|
33
|
+
// test/ directory
|
|
34
|
+
/\/tests\//,
|
|
35
|
+
// tests/ directory
|
|
36
|
+
/\.stories\.[jt]sx?$/,
|
|
37
|
+
// Storybook files
|
|
38
|
+
/\.config\.[jt]s$/,
|
|
39
|
+
// Config files
|
|
40
|
+
/example/i,
|
|
41
|
+
// Example files
|
|
42
|
+
/demo/i,
|
|
43
|
+
// Demo files
|
|
44
|
+
/fixture/i,
|
|
45
|
+
// Test fixtures
|
|
46
|
+
/mock/i
|
|
47
|
+
// Mock files
|
|
48
|
+
];
|
|
49
|
+
function shouldAlwaysExcludeFile(filePath) {
|
|
50
|
+
return ALWAYS_EXCLUDED_FILES.some((pattern) => pattern.test(filePath));
|
|
51
|
+
}
|
|
52
|
+
function shouldExcludeFile(filePath, patternCategory) {
|
|
53
|
+
if (shouldAlwaysExcludeFile(filePath)) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (patternCategory === "secrets" || patternCategory === "exposed-secrets") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(filePath));
|
|
60
|
+
}
|
|
61
|
+
var SQL_CONTEXT_KEYWORDS = [
|
|
62
|
+
"SELECT",
|
|
63
|
+
"INSERT",
|
|
64
|
+
"UPDATE",
|
|
65
|
+
"DELETE",
|
|
66
|
+
"FROM",
|
|
67
|
+
"WHERE",
|
|
68
|
+
"JOIN",
|
|
69
|
+
"query",
|
|
70
|
+
"execute",
|
|
71
|
+
"sql",
|
|
72
|
+
"prisma",
|
|
73
|
+
"knex",
|
|
74
|
+
"sequelize",
|
|
75
|
+
"createQueryBuilder",
|
|
76
|
+
"rawQuery",
|
|
77
|
+
".raw("
|
|
78
|
+
];
|
|
79
|
+
function isInSQLContext(line, surroundingLines) {
|
|
80
|
+
const allContent = [line, ...surroundingLines].join(" ").toLowerCase();
|
|
81
|
+
return SQL_CONTEXT_KEYWORDS.some(
|
|
82
|
+
(keyword) => allContent.includes(keyword.toLowerCase())
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
var VULNERABILITY_PATTERNS = [
|
|
86
|
+
// ============================================
|
|
87
|
+
// CRITICAL: Injection vulnerabilities
|
|
88
|
+
// ============================================
|
|
89
|
+
{
|
|
90
|
+
pattern: "eval(",
|
|
91
|
+
metadata: {
|
|
92
|
+
type: "vulnerability",
|
|
93
|
+
severity: "critical",
|
|
94
|
+
category: "injection",
|
|
95
|
+
description: "eval() can execute arbitrary code - potential RCE",
|
|
96
|
+
cwe: "CWE-95",
|
|
97
|
+
fix: "Use safer alternatives like JSON.parse() or a sandboxed interpreter"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
pattern: "new Function(",
|
|
102
|
+
metadata: {
|
|
103
|
+
type: "vulnerability",
|
|
104
|
+
severity: "critical",
|
|
105
|
+
category: "injection",
|
|
106
|
+
description: "new Function() can execute arbitrary code",
|
|
107
|
+
cwe: "CWE-95",
|
|
108
|
+
fix: "Avoid dynamic function creation from user input"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
pattern: "exec(",
|
|
113
|
+
metadata: {
|
|
114
|
+
type: "vulnerability",
|
|
115
|
+
severity: "critical",
|
|
116
|
+
category: "injection",
|
|
117
|
+
description: "Command execution - potential command injection",
|
|
118
|
+
cwe: "CWE-78",
|
|
119
|
+
fix: "Use parameterized commands and validate/sanitize all inputs"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
pattern: "execSync(",
|
|
124
|
+
metadata: {
|
|
125
|
+
type: "vulnerability",
|
|
126
|
+
severity: "critical",
|
|
127
|
+
category: "injection",
|
|
128
|
+
description: "Synchronous command execution - potential injection",
|
|
129
|
+
cwe: "CWE-78",
|
|
130
|
+
fix: "Use spawn with argument arrays instead of shell strings"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
pattern: "spawn(",
|
|
135
|
+
metadata: {
|
|
136
|
+
type: "vulnerability",
|
|
137
|
+
severity: "serious",
|
|
138
|
+
category: "injection",
|
|
139
|
+
description: "Process spawn - verify inputs are sanitized",
|
|
140
|
+
cwe: "CWE-78",
|
|
141
|
+
fix: "Use shell: false and pass arguments as array"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
pattern: "child_process",
|
|
146
|
+
metadata: {
|
|
147
|
+
type: "vulnerability",
|
|
148
|
+
severity: "serious",
|
|
149
|
+
category: "injection",
|
|
150
|
+
description: "Child process module - review for command injection",
|
|
151
|
+
cwe: "CWE-78",
|
|
152
|
+
fix: "Validate all inputs passed to child processes"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
// ============================================
|
|
156
|
+
// CRITICAL: SQL Injection patterns
|
|
157
|
+
// NOTE: ${} is NOT flagged here - we check SQL context in isFalsePositive
|
|
158
|
+
// ============================================
|
|
159
|
+
{
|
|
160
|
+
pattern: "SELECT * FROM",
|
|
161
|
+
metadata: {
|
|
162
|
+
type: "vulnerability",
|
|
163
|
+
severity: "moderate",
|
|
164
|
+
category: "sql-injection",
|
|
165
|
+
description: "Raw SQL query detected - verify parameterization",
|
|
166
|
+
cwe: "CWE-89",
|
|
167
|
+
fix: "Use ORM or parameterized queries"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
pattern: "INSERT INTO",
|
|
172
|
+
metadata: {
|
|
173
|
+
type: "vulnerability",
|
|
174
|
+
severity: "moderate",
|
|
175
|
+
category: "sql-injection",
|
|
176
|
+
description: "Raw SQL INSERT - verify parameterization",
|
|
177
|
+
cwe: "CWE-89",
|
|
178
|
+
fix: "Use parameterized queries"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
pattern: "DELETE FROM",
|
|
183
|
+
metadata: {
|
|
184
|
+
type: "vulnerability",
|
|
185
|
+
severity: "moderate",
|
|
186
|
+
category: "sql-injection",
|
|
187
|
+
description: "Raw SQL DELETE - verify parameterization",
|
|
188
|
+
cwe: "CWE-89",
|
|
189
|
+
fix: "Use parameterized queries"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
pattern: ".raw(`",
|
|
194
|
+
metadata: {
|
|
195
|
+
type: "vulnerability",
|
|
196
|
+
severity: "serious",
|
|
197
|
+
category: "sql-injection",
|
|
198
|
+
description: "Raw query with template literal - high injection risk",
|
|
199
|
+
cwe: "CWE-89",
|
|
200
|
+
fix: "Avoid raw queries with interpolation or use proper escaping"
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
pattern: ".raw('",
|
|
205
|
+
metadata: {
|
|
206
|
+
type: "vulnerability",
|
|
207
|
+
severity: "moderate",
|
|
208
|
+
category: "sql-injection",
|
|
209
|
+
description: "Raw query method - verify for injection risk",
|
|
210
|
+
cwe: "CWE-89",
|
|
211
|
+
fix: "Use parameterized queries instead of raw SQL"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
pattern: '.raw("',
|
|
216
|
+
metadata: {
|
|
217
|
+
type: "vulnerability",
|
|
218
|
+
severity: "moderate",
|
|
219
|
+
category: "sql-injection",
|
|
220
|
+
description: "Raw query method - verify for injection risk",
|
|
221
|
+
cwe: "CWE-89",
|
|
222
|
+
fix: "Use parameterized queries instead of raw SQL"
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
pattern: "`SELECT",
|
|
227
|
+
metadata: {
|
|
228
|
+
type: "vulnerability",
|
|
229
|
+
severity: "serious",
|
|
230
|
+
category: "sql-injection",
|
|
231
|
+
description: "SQL in template literal - check for injection",
|
|
232
|
+
cwe: "CWE-89",
|
|
233
|
+
fix: "Use parameterized queries with placeholders"
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
pattern: "`INSERT",
|
|
238
|
+
metadata: {
|
|
239
|
+
type: "vulnerability",
|
|
240
|
+
severity: "serious",
|
|
241
|
+
category: "sql-injection",
|
|
242
|
+
description: "SQL INSERT in template literal - check for injection",
|
|
243
|
+
cwe: "CWE-89",
|
|
244
|
+
fix: "Use parameterized queries with placeholders"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
pattern: "`UPDATE",
|
|
249
|
+
metadata: {
|
|
250
|
+
type: "vulnerability",
|
|
251
|
+
severity: "serious",
|
|
252
|
+
category: "sql-injection",
|
|
253
|
+
description: "SQL UPDATE in template literal - check for injection",
|
|
254
|
+
cwe: "CWE-89",
|
|
255
|
+
fix: "Use parameterized queries with placeholders"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
pattern: "`DELETE",
|
|
260
|
+
metadata: {
|
|
261
|
+
type: "vulnerability",
|
|
262
|
+
severity: "serious",
|
|
263
|
+
category: "sql-injection",
|
|
264
|
+
description: "SQL DELETE in template literal - check for injection",
|
|
265
|
+
cwe: "CWE-89",
|
|
266
|
+
fix: "Use parameterized queries with placeholders"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
// ============================================
|
|
270
|
+
// CRITICAL: XSS vulnerabilities
|
|
271
|
+
// ============================================
|
|
272
|
+
{
|
|
273
|
+
pattern: "innerHTML",
|
|
274
|
+
metadata: {
|
|
275
|
+
type: "vulnerability",
|
|
276
|
+
severity: "serious",
|
|
277
|
+
category: "xss",
|
|
278
|
+
description: "innerHTML can inject malicious scripts",
|
|
279
|
+
cwe: "CWE-79",
|
|
280
|
+
fix: "Use textContent or sanitize HTML with DOMPurify"
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
pattern: "outerHTML",
|
|
285
|
+
metadata: {
|
|
286
|
+
type: "vulnerability",
|
|
287
|
+
severity: "serious",
|
|
288
|
+
category: "xss",
|
|
289
|
+
description: "outerHTML can inject malicious scripts",
|
|
290
|
+
cwe: "CWE-79",
|
|
291
|
+
fix: "Avoid outerHTML with user input"
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
pattern: "document.write",
|
|
296
|
+
metadata: {
|
|
297
|
+
type: "vulnerability",
|
|
298
|
+
severity: "serious",
|
|
299
|
+
category: "xss",
|
|
300
|
+
description: "document.write can inject malicious content",
|
|
301
|
+
cwe: "CWE-79",
|
|
302
|
+
fix: "Use DOM methods like createElement instead"
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
pattern: "dangerouslySetInnerHTML",
|
|
307
|
+
metadata: {
|
|
308
|
+
type: "vulnerability",
|
|
309
|
+
severity: "serious",
|
|
310
|
+
category: "xss",
|
|
311
|
+
description: "React dangerouslySetInnerHTML - XSS risk",
|
|
312
|
+
cwe: "CWE-79",
|
|
313
|
+
fix: "Sanitize with DOMPurify before using"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
pattern: "v-html",
|
|
318
|
+
metadata: {
|
|
319
|
+
type: "vulnerability",
|
|
320
|
+
severity: "serious",
|
|
321
|
+
category: "xss",
|
|
322
|
+
description: "Vue v-html directive - XSS risk",
|
|
323
|
+
cwe: "CWE-79",
|
|
324
|
+
fix: "Sanitize content or use v-text"
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
pattern: "[innerHTML]",
|
|
329
|
+
metadata: {
|
|
330
|
+
type: "vulnerability",
|
|
331
|
+
severity: "serious",
|
|
332
|
+
category: "xss",
|
|
333
|
+
description: "Angular innerHTML binding - XSS risk",
|
|
334
|
+
cwe: "CWE-79",
|
|
335
|
+
fix: "Use Angular DomSanitizer"
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
// ============================================
|
|
339
|
+
// CRITICAL: Hardcoded secrets
|
|
340
|
+
// More specific patterns to reduce false positives
|
|
341
|
+
// ============================================
|
|
342
|
+
{
|
|
343
|
+
pattern: "password = '",
|
|
344
|
+
metadata: {
|
|
345
|
+
type: "vulnerability",
|
|
346
|
+
severity: "critical",
|
|
347
|
+
category: "secrets",
|
|
348
|
+
description: "Hardcoded password in string",
|
|
349
|
+
cwe: "CWE-798",
|
|
350
|
+
fix: "Use environment variables or secret management"
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
pattern: 'password = "',
|
|
355
|
+
metadata: {
|
|
356
|
+
type: "vulnerability",
|
|
357
|
+
severity: "critical",
|
|
358
|
+
category: "secrets",
|
|
359
|
+
description: "Hardcoded password in string",
|
|
360
|
+
cwe: "CWE-798",
|
|
361
|
+
fix: "Use environment variables or secret management"
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
pattern: "password: '",
|
|
366
|
+
metadata: {
|
|
367
|
+
type: "vulnerability",
|
|
368
|
+
severity: "critical",
|
|
369
|
+
category: "secrets",
|
|
370
|
+
description: "Hardcoded password in config",
|
|
371
|
+
cwe: "CWE-798",
|
|
372
|
+
fix: "Use environment variables or secret management"
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
pattern: 'password: "',
|
|
377
|
+
metadata: {
|
|
378
|
+
type: "vulnerability",
|
|
379
|
+
severity: "critical",
|
|
380
|
+
category: "secrets",
|
|
381
|
+
description: "Hardcoded password in config",
|
|
382
|
+
cwe: "CWE-798",
|
|
383
|
+
fix: "Use environment variables or secret management"
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
pattern: "api_key = '",
|
|
388
|
+
metadata: {
|
|
389
|
+
type: "vulnerability",
|
|
390
|
+
severity: "critical",
|
|
391
|
+
category: "secrets",
|
|
392
|
+
description: "Hardcoded API key",
|
|
393
|
+
cwe: "CWE-798",
|
|
394
|
+
fix: "Use environment variables"
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
pattern: 'api_key = "',
|
|
399
|
+
metadata: {
|
|
400
|
+
type: "vulnerability",
|
|
401
|
+
severity: "critical",
|
|
402
|
+
category: "secrets",
|
|
403
|
+
description: "Hardcoded API key",
|
|
404
|
+
cwe: "CWE-798",
|
|
405
|
+
fix: "Use environment variables"
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
pattern: "apiKey: '",
|
|
410
|
+
metadata: {
|
|
411
|
+
type: "vulnerability",
|
|
412
|
+
severity: "critical",
|
|
413
|
+
category: "secrets",
|
|
414
|
+
description: "Hardcoded API key in config",
|
|
415
|
+
cwe: "CWE-798",
|
|
416
|
+
fix: "Use environment variables"
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
pattern: 'apiKey: "',
|
|
421
|
+
metadata: {
|
|
422
|
+
type: "vulnerability",
|
|
423
|
+
severity: "critical",
|
|
424
|
+
category: "secrets",
|
|
425
|
+
description: "Hardcoded API key in config",
|
|
426
|
+
cwe: "CWE-798",
|
|
427
|
+
fix: "Use environment variables"
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
pattern: "secret = '",
|
|
432
|
+
metadata: {
|
|
433
|
+
type: "vulnerability",
|
|
434
|
+
severity: "critical",
|
|
435
|
+
category: "secrets",
|
|
436
|
+
description: "Hardcoded secret",
|
|
437
|
+
cwe: "CWE-798",
|
|
438
|
+
fix: "Use environment variables or secret management"
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
pattern: 'secret = "',
|
|
443
|
+
metadata: {
|
|
444
|
+
type: "vulnerability",
|
|
445
|
+
severity: "critical",
|
|
446
|
+
category: "secrets",
|
|
447
|
+
description: "Hardcoded secret",
|
|
448
|
+
cwe: "CWE-798",
|
|
449
|
+
fix: "Use environment variables or secret management"
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
pattern: "AWS_SECRET_ACCESS_KEY=",
|
|
454
|
+
metadata: {
|
|
455
|
+
type: "vulnerability",
|
|
456
|
+
severity: "critical",
|
|
457
|
+
category: "secrets",
|
|
458
|
+
description: "AWS secret key assignment",
|
|
459
|
+
cwe: "CWE-798",
|
|
460
|
+
fix: "Use IAM roles or AWS Secrets Manager"
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
pattern: "'Bearer ",
|
|
465
|
+
metadata: {
|
|
466
|
+
type: "vulnerability",
|
|
467
|
+
severity: "serious",
|
|
468
|
+
category: "secrets",
|
|
469
|
+
description: "Hardcoded bearer token in string",
|
|
470
|
+
cwe: "CWE-798",
|
|
471
|
+
fix: "Use environment variables for tokens"
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
pattern: '"Bearer ',
|
|
476
|
+
metadata: {
|
|
477
|
+
type: "vulnerability",
|
|
478
|
+
severity: "serious",
|
|
479
|
+
category: "secrets",
|
|
480
|
+
description: "Hardcoded bearer token in string",
|
|
481
|
+
cwe: "CWE-798",
|
|
482
|
+
fix: "Use environment variables for tokens"
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
// ============================================
|
|
486
|
+
// SERIOUS: Authentication issues
|
|
487
|
+
// ============================================
|
|
488
|
+
{
|
|
489
|
+
pattern: "password ==",
|
|
490
|
+
metadata: {
|
|
491
|
+
type: "vulnerability",
|
|
492
|
+
severity: "critical",
|
|
493
|
+
category: "auth",
|
|
494
|
+
description: "Plain text password comparison",
|
|
495
|
+
cwe: "CWE-256",
|
|
496
|
+
fix: "Use bcrypt.compare() or similar secure comparison"
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
pattern: "password ===",
|
|
501
|
+
metadata: {
|
|
502
|
+
type: "vulnerability",
|
|
503
|
+
severity: "critical",
|
|
504
|
+
category: "auth",
|
|
505
|
+
description: "Plain text password comparison",
|
|
506
|
+
cwe: "CWE-256",
|
|
507
|
+
fix: "Use bcrypt.compare() or similar secure comparison"
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
pattern: "MD5(",
|
|
512
|
+
metadata: {
|
|
513
|
+
type: "vulnerability",
|
|
514
|
+
severity: "serious",
|
|
515
|
+
category: "crypto",
|
|
516
|
+
description: "MD5 is cryptographically broken",
|
|
517
|
+
cwe: "CWE-328",
|
|
518
|
+
fix: "Use SHA-256 or bcrypt for passwords"
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
pattern: "md5(",
|
|
523
|
+
metadata: {
|
|
524
|
+
type: "vulnerability",
|
|
525
|
+
severity: "serious",
|
|
526
|
+
category: "crypto",
|
|
527
|
+
description: "MD5 is cryptographically broken",
|
|
528
|
+
cwe: "CWE-328",
|
|
529
|
+
fix: "Use SHA-256 or bcrypt for passwords"
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
pattern: "SHA1(",
|
|
534
|
+
metadata: {
|
|
535
|
+
type: "vulnerability",
|
|
536
|
+
severity: "moderate",
|
|
537
|
+
category: "crypto",
|
|
538
|
+
description: "SHA1 is deprecated for security use",
|
|
539
|
+
cwe: "CWE-328",
|
|
540
|
+
fix: "Use SHA-256 or stronger"
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
pattern: "sha1(",
|
|
545
|
+
metadata: {
|
|
546
|
+
type: "vulnerability",
|
|
547
|
+
severity: "moderate",
|
|
548
|
+
category: "crypto",
|
|
549
|
+
description: "SHA1 is deprecated for security use",
|
|
550
|
+
cwe: "CWE-328",
|
|
551
|
+
fix: "Use SHA-256 or stronger"
|
|
552
|
+
}
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
pattern: "Math.random()",
|
|
556
|
+
metadata: {
|
|
557
|
+
type: "vulnerability",
|
|
558
|
+
severity: "serious",
|
|
559
|
+
category: "crypto",
|
|
560
|
+
description: "Math.random() is not cryptographically secure",
|
|
561
|
+
cwe: "CWE-338",
|
|
562
|
+
fix: "Use crypto.randomBytes() or crypto.getRandomValues()"
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
// ============================================
|
|
566
|
+
// SERIOUS: Insecure configurations
|
|
567
|
+
// ============================================
|
|
568
|
+
{
|
|
569
|
+
pattern: "cors: true",
|
|
570
|
+
metadata: {
|
|
571
|
+
type: "vulnerability",
|
|
572
|
+
severity: "moderate",
|
|
573
|
+
category: "config",
|
|
574
|
+
description: "CORS enabled - verify origin restrictions",
|
|
575
|
+
cwe: "CWE-942",
|
|
576
|
+
fix: "Specify allowed origins explicitly"
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
pattern: "origin: '*'",
|
|
581
|
+
metadata: {
|
|
582
|
+
type: "vulnerability",
|
|
583
|
+
severity: "serious",
|
|
584
|
+
category: "config",
|
|
585
|
+
description: "CORS allows all origins",
|
|
586
|
+
cwe: "CWE-942",
|
|
587
|
+
fix: "Restrict to specific trusted origins"
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
pattern: 'origin: "*"',
|
|
592
|
+
metadata: {
|
|
593
|
+
type: "vulnerability",
|
|
594
|
+
severity: "serious",
|
|
595
|
+
category: "config",
|
|
596
|
+
description: "CORS allows all origins",
|
|
597
|
+
cwe: "CWE-942",
|
|
598
|
+
fix: "Restrict to specific trusted origins"
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
pattern: "secure: false",
|
|
603
|
+
metadata: {
|
|
604
|
+
type: "vulnerability",
|
|
605
|
+
severity: "serious",
|
|
606
|
+
category: "config",
|
|
607
|
+
description: "Insecure cookie/connection setting",
|
|
608
|
+
cwe: "CWE-614",
|
|
609
|
+
fix: "Set secure: true in production"
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
pattern: "httpOnly: false",
|
|
614
|
+
metadata: {
|
|
615
|
+
type: "vulnerability",
|
|
616
|
+
severity: "serious",
|
|
617
|
+
category: "config",
|
|
618
|
+
description: "Cookie accessible to JavaScript",
|
|
619
|
+
cwe: "CWE-1004",
|
|
620
|
+
fix: "Set httpOnly: true to prevent XSS cookie theft"
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
pattern: "rejectUnauthorized: false",
|
|
625
|
+
metadata: {
|
|
626
|
+
type: "vulnerability",
|
|
627
|
+
severity: "critical",
|
|
628
|
+
category: "config",
|
|
629
|
+
description: "TLS certificate validation disabled",
|
|
630
|
+
cwe: "CWE-295",
|
|
631
|
+
fix: "Enable certificate validation in production"
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
pattern: "NODE_TLS_REJECT_UNAUTHORIZED",
|
|
636
|
+
metadata: {
|
|
637
|
+
type: "vulnerability",
|
|
638
|
+
severity: "critical",
|
|
639
|
+
category: "config",
|
|
640
|
+
description: "TLS validation may be disabled",
|
|
641
|
+
cwe: "CWE-295",
|
|
642
|
+
fix: "Never disable TLS validation in production"
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
// ============================================
|
|
646
|
+
// MODERATE: Common bugs and issues
|
|
647
|
+
// ============================================
|
|
648
|
+
{
|
|
649
|
+
pattern: ".forEach(async",
|
|
650
|
+
metadata: {
|
|
651
|
+
type: "vulnerability",
|
|
652
|
+
severity: "serious",
|
|
653
|
+
category: "async",
|
|
654
|
+
description: "async forEach does not await - unexpected behavior",
|
|
655
|
+
cwe: "CWE-703",
|
|
656
|
+
fix: "Use for...of loop or Promise.all(arr.map())"
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
pattern: "JSON.parse(",
|
|
661
|
+
metadata: {
|
|
662
|
+
type: "vulnerability",
|
|
663
|
+
severity: "moderate",
|
|
664
|
+
category: "error-handling",
|
|
665
|
+
description: "JSON.parse can throw - needs try/catch",
|
|
666
|
+
cwe: "CWE-755",
|
|
667
|
+
fix: "Wrap in try/catch block"
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
pattern: "atob(",
|
|
672
|
+
metadata: {
|
|
673
|
+
type: "vulnerability",
|
|
674
|
+
severity: "low",
|
|
675
|
+
category: "encoding",
|
|
676
|
+
description: "atob can throw on invalid input",
|
|
677
|
+
cwe: "CWE-755",
|
|
678
|
+
fix: "Wrap in try/catch and validate input"
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
// ============================================
|
|
682
|
+
// Privacy & Compliance patterns
|
|
683
|
+
// ============================================
|
|
684
|
+
{
|
|
685
|
+
pattern: "console.log(",
|
|
686
|
+
metadata: {
|
|
687
|
+
type: "vulnerability",
|
|
688
|
+
severity: "low",
|
|
689
|
+
category: "logging",
|
|
690
|
+
description: "Console logging - may leak sensitive data",
|
|
691
|
+
cwe: "CWE-532",
|
|
692
|
+
fix: "Remove or replace with proper logging in production"
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
pattern: "localStorage.setItem",
|
|
697
|
+
metadata: {
|
|
698
|
+
type: "vulnerability",
|
|
699
|
+
severity: "moderate",
|
|
700
|
+
category: "storage",
|
|
701
|
+
description: "localStorage is accessible to XSS attacks",
|
|
702
|
+
cwe: "CWE-922",
|
|
703
|
+
fix: "Avoid storing sensitive data in localStorage"
|
|
704
|
+
}
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
pattern: "sessionStorage.setItem",
|
|
708
|
+
metadata: {
|
|
709
|
+
type: "vulnerability",
|
|
710
|
+
severity: "moderate",
|
|
711
|
+
category: "storage",
|
|
712
|
+
description: "sessionStorage is accessible to XSS attacks",
|
|
713
|
+
cwe: "CWE-922",
|
|
714
|
+
fix: "Avoid storing sensitive data in sessionStorage"
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
];
|
|
718
|
+
var vulnerabilityTrie = null;
|
|
719
|
+
function getVulnerabilityTrie() {
|
|
720
|
+
if (!vulnerabilityTrie) {
|
|
721
|
+
vulnerabilityTrie = new AhoCorasick();
|
|
722
|
+
for (const { pattern, metadata } of VULNERABILITY_PATTERNS) {
|
|
723
|
+
vulnerabilityTrie.addPattern(pattern, metadata, metadata);
|
|
724
|
+
}
|
|
725
|
+
vulnerabilityTrie.build();
|
|
726
|
+
console.error(` \u{1F527} Loaded ${VULNERABILITY_PATTERNS.length} vulnerability signatures into trie`);
|
|
727
|
+
}
|
|
728
|
+
return vulnerabilityTrie;
|
|
729
|
+
}
|
|
730
|
+
function scanForVulnerabilities(code, filePath) {
|
|
731
|
+
if (shouldAlwaysExcludeFile(filePath)) {
|
|
732
|
+
return [];
|
|
733
|
+
}
|
|
734
|
+
const trie = getVulnerabilityTrie();
|
|
735
|
+
const rawMatches = trie.search(code);
|
|
736
|
+
const lines = code.split("\n");
|
|
737
|
+
const matches = [];
|
|
738
|
+
const seen = /* @__PURE__ */ new Set();
|
|
739
|
+
for (const match of rawMatches) {
|
|
740
|
+
const key = `${match.line}:${match.pattern}`;
|
|
741
|
+
if (seen.has(key)) continue;
|
|
742
|
+
seen.add(key);
|
|
743
|
+
const meta = match.metadata;
|
|
744
|
+
if (shouldExcludeFile(filePath, meta.category || "")) continue;
|
|
745
|
+
if (isFalsePositive(code, match, filePath, lines)) continue;
|
|
746
|
+
const vulnMatch = {
|
|
747
|
+
pattern: match.pattern,
|
|
748
|
+
line: match.line,
|
|
749
|
+
column: match.column,
|
|
750
|
+
severity: meta.severity,
|
|
751
|
+
category: meta.category || "unknown",
|
|
752
|
+
description: meta.description || "",
|
|
753
|
+
fix: meta.fix || ""
|
|
754
|
+
};
|
|
755
|
+
if (meta.cwe !== void 0) {
|
|
756
|
+
vulnMatch.cwe = meta.cwe;
|
|
757
|
+
}
|
|
758
|
+
matches.push(vulnMatch);
|
|
759
|
+
}
|
|
760
|
+
return matches;
|
|
761
|
+
}
|
|
762
|
+
function getSurroundingLines(lines, lineNum, range = 3) {
|
|
763
|
+
const start = Math.max(0, lineNum - range - 1);
|
|
764
|
+
const end = Math.min(lines.length, lineNum + range);
|
|
765
|
+
return lines.slice(start, end);
|
|
766
|
+
}
|
|
767
|
+
function isFalsePositive(_code, match, filePath, lines) {
|
|
768
|
+
const line = lines[match.line - 1] || "";
|
|
769
|
+
const trimmedLine = line.trim();
|
|
770
|
+
const pattern = match.pattern;
|
|
771
|
+
const category = match.metadata?.category || "";
|
|
772
|
+
if (filePath.includes("signature") || filePath.includes("patterns") || filePath.includes("rules")) {
|
|
773
|
+
if (/pattern\s*[:=]/.test(line)) {
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
if (/^\s*(pattern|regex|rule|signature)\s*[:=]/.test(trimmedLine)) {
|
|
778
|
+
return true;
|
|
779
|
+
}
|
|
780
|
+
if (isTestFile(filePath)) {
|
|
781
|
+
if (category === "secrets") {
|
|
782
|
+
if (/test|mock|fake|dummy|example|fixture|sample|placeholder/i.test(line)) {
|
|
783
|
+
return true;
|
|
784
|
+
}
|
|
785
|
+
if (/'[a-z_]*password[a-z_0-9]*'|"[a-z_]*password[a-z_0-9]*"|'[a-z_]*secret[a-z_0-9]*'|"[a-z_]*secret[a-z_0-9]*"/i.test(line)) {
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
if (/sk-[a-z0-9]{10,20}"|'sk-[a-z0-9]{10,20}'|api[_-]?key.*['"][a-z0-9_-]{5,30}['"]/i.test(line)) {
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
if (trimmedLine.startsWith("//") || trimmedLine.startsWith("*") || trimmedLine.startsWith("/*") || trimmedLine.startsWith("#") || trimmedLine.startsWith("<!--")) {
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
if (/^\s*\*\s/.test(line) || /@(param|returns|example|description|see|link)/i.test(line)) {
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
if (/^\s*(description|fix|message|help|hint|reason|why)\s*[:=]/.test(trimmedLine)) {
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
if (/^\s*(interface|type|export\s+interface|export\s+type)\s/.test(line)) {
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
if (/:\s*(string|number|boolean|any|unknown|null|undefined|void)\s*(;|,|\)|$)/.test(line)) {
|
|
807
|
+
return true;
|
|
808
|
+
}
|
|
809
|
+
if (/^\s*\w+\s*\??\s*:\s*(string|number|boolean|any)/.test(trimmedLine)) {
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
if (/process\.env|import\.meta\.env|getenv|os\.environ|Deno\.env|\.env\.|config\.\w+|settings\.\w+/.test(line)) {
|
|
813
|
+
return true;
|
|
814
|
+
}
|
|
815
|
+
if (filePath.endsWith("package-lock.json") || filePath.endsWith("yarn.lock") || filePath.endsWith("pnpm-lock.yaml") || filePath.includes("node_modules/")) {
|
|
816
|
+
return true;
|
|
817
|
+
}
|
|
818
|
+
if (/^\s*(severity|category|type|level|priority|cwe|owasp)\s*:\s*['"]/.test(trimmedLine)) {
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
if (category === "sql-injection") {
|
|
822
|
+
const surroundingLines = getSurroundingLines(lines, match.line);
|
|
823
|
+
if (!isInSQLContext(line, surroundingLines)) {
|
|
824
|
+
return true;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (category === "secrets" || category === "auth") {
|
|
828
|
+
if (/\(\s*[^)]*\w+\s*:\s*(string|any)/.test(line)) {
|
|
829
|
+
return true;
|
|
830
|
+
}
|
|
831
|
+
if (/\{\s*\w*password\w*\s*(,|\}|:)/.test(line) && !/'|"|`/.test(line.split(/password/i)[1] || "")) {
|
|
832
|
+
return true;
|
|
833
|
+
}
|
|
834
|
+
if (/=\s*(process\.env|config\.|options\.|settings\.|env\.)/.test(line)) {
|
|
835
|
+
return true;
|
|
836
|
+
}
|
|
837
|
+
if (/password\s*[=:](?!\s*['"`])/.test(line)) {
|
|
838
|
+
return true;
|
|
839
|
+
}
|
|
840
|
+
if (/password\s*=\s*\w+(\.|$)/.test(line) && !/'|"|`/.test(line)) {
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
843
|
+
if (/error|message|log|warn|info|debug|throw|new Error/i.test(line)) {
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
if (/regex|RegExp|\/.*password.*\//i.test(line)) {
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (category === "logging") {
|
|
851
|
+
if (pattern === "console.error(" || pattern === "console.warn(") {
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
if (/catch|error|err\b/.test(line)) {
|
|
855
|
+
return true;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (category === "config") {
|
|
859
|
+
if (/secure:\s*true/.test(line) || /httpOnly:\s*true/.test(line)) {
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
if (/NODE_ENV|process\.env|production|development/.test(line)) {
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
if (/if\s*\(|ternary|\?.*:/.test(line)) {
|
|
866
|
+
return true;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
if (category === "crypto") {
|
|
870
|
+
if (/checksum|hash.*file|etag|cache.*key|fingerprint|integrity|content.*hash/i.test(line)) {
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
if (pattern === "Math.random()") {
|
|
874
|
+
if (!/token|secret|password|key|auth|session|csrf|nonce/i.test(line)) {
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
if (category === "async") {
|
|
880
|
+
if (/\/\/.*intentional|\/\/.*fire.?and.?forget|\/\/.*parallel/i.test(line)) {
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
if (/password.*length|validate.*password|check.*password|verify.*password|is.*valid/i.test(line)) {
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
if (/bcrypt|argon|scrypt|pbkdf|compare.*hash|hash.*compare|verify.*hash/i.test(line)) {
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
if (/z\.|yup\.|joi\.|schema|validation|validator/i.test(line)) {
|
|
891
|
+
return true;
|
|
892
|
+
}
|
|
893
|
+
if (/^\s*(import|require|from)\s/.test(trimmedLine)) {
|
|
894
|
+
return true;
|
|
895
|
+
}
|
|
896
|
+
if (/example|demo|sample|tutorial|readme/i.test(filePath)) {
|
|
897
|
+
return true;
|
|
898
|
+
}
|
|
899
|
+
return false;
|
|
900
|
+
}
|
|
901
|
+
function isTestFile(filePath) {
|
|
902
|
+
return /\.(test|spec)\.[jt]sx?$/.test(filePath) || /__tests__\//.test(filePath) || /test\//.test(filePath) || /tests\//.test(filePath) || /\.stories\.[jt]sx?$/.test(filePath);
|
|
903
|
+
}
|
|
904
|
+
function getVulnerabilityStats() {
|
|
905
|
+
const byCategory = {};
|
|
906
|
+
const bySeverity = {};
|
|
907
|
+
for (const { metadata } of VULNERABILITY_PATTERNS) {
|
|
908
|
+
const cat = metadata.category || "unknown";
|
|
909
|
+
const sev = metadata.severity || "unknown";
|
|
910
|
+
byCategory[cat] = (byCategory[cat] || 0) + 1;
|
|
911
|
+
bySeverity[sev] = (bySeverity[sev] || 0) + 1;
|
|
912
|
+
}
|
|
913
|
+
return {
|
|
914
|
+
total: VULNERABILITY_PATTERNS.length,
|
|
915
|
+
byCategory,
|
|
916
|
+
bySeverity
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
export {
|
|
921
|
+
shouldAlwaysExcludeFile,
|
|
922
|
+
shouldExcludeFile,
|
|
923
|
+
getVulnerabilityTrie,
|
|
924
|
+
scanForVulnerabilities,
|
|
925
|
+
getVulnerabilityStats
|
|
926
|
+
};
|
|
927
|
+
//# sourceMappingURL=chunk-MR755QGT.js.map
|