@indicated/vibeguard 1.0.0 → 1.1.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/PROGRESS.md +42 -13
- package/dist/api/license.d.ts +14 -2
- package/dist/api/license.d.ts.map +1 -1
- package/dist/api/license.js +46 -13
- package/dist/api/license.js.map +1 -1
- package/dist/cli/commands/scan.d.ts.map +1 -1
- package/dist/cli/commands/scan.js +7 -2
- package/dist/cli/commands/scan.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +3 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +70 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +3 -2
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +27 -4
- package/dist/cli/output.js.map +1 -1
- package/dist/scanner/index.d.ts +4 -1
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +15 -2
- package/dist/scanner/index.js.map +1 -1
- package/dist/scanner/parsers/javascript.d.ts.map +1 -1
- package/dist/scanner/parsers/javascript.js +6 -0
- package/dist/scanner/parsers/javascript.js.map +1 -1
- package/dist/scanner/parsers/python.d.ts.map +1 -1
- package/dist/scanner/parsers/python.js +2 -0
- package/dist/scanner/parsers/python.js.map +1 -1
- package/dist/scanner/rules/definitions.d.ts.map +1 -1
- package/dist/scanner/rules/definitions.js +52 -4
- package/dist/scanner/rules/definitions.js.map +1 -1
- package/dist/scanner/rules/matcher.d.ts.map +1 -1
- package/dist/scanner/rules/matcher.js +1 -0
- package/dist/scanner/rules/matcher.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/api/license.ts +50 -15
- package/src/cli/commands/scan.ts +8 -2
- package/src/cli/commands/upgrade.ts +76 -0
- package/src/cli/index.ts +2 -0
- package/src/cli/output.ts +28 -5
- package/src/scanner/index.ts +19 -3
- package/src/scanner/parsers/javascript.ts +6 -0
- package/src/scanner/parsers/python.ts +2 -0
- package/src/scanner/rules/definitions.ts +53 -4
- package/src/scanner/rules/matcher.ts +1 -0
- package/src/types.ts +3 -0
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { SecurityRule } from '../../types';
|
|
2
2
|
|
|
3
3
|
export const securityRules: SecurityRule[] = [
|
|
4
|
+
// ============================================
|
|
5
|
+
// FREE TIER RULES - Basic vulnerabilities
|
|
6
|
+
// ============================================
|
|
7
|
+
|
|
4
8
|
// CRITICAL
|
|
5
9
|
{
|
|
6
10
|
id: 'hardcoded-secret',
|
|
7
11
|
name: 'Hardcoded API Key/Secret',
|
|
8
12
|
description: 'Hardcoded secrets can be extracted from source code and used maliciously',
|
|
9
13
|
severity: 'critical',
|
|
14
|
+
tier: 'free',
|
|
10
15
|
languages: ['javascript', 'typescript', 'python'],
|
|
11
16
|
patterns: [
|
|
12
17
|
/(['"`])(?:sk-[a-zA-Z0-9]{20,})\1/,
|
|
@@ -23,6 +28,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
23
28
|
name: 'SQL Injection Vulnerability',
|
|
24
29
|
description: 'User input directly concatenated into SQL queries can allow attackers to execute arbitrary SQL',
|
|
25
30
|
severity: 'critical',
|
|
31
|
+
tier: 'free',
|
|
26
32
|
languages: ['javascript', 'typescript', 'python'],
|
|
27
33
|
astMatcher: 'sql-injection',
|
|
28
34
|
fix: 'Use parameterized queries or prepared statements',
|
|
@@ -32,6 +38,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
32
38
|
name: 'Dangerous eval() Usage',
|
|
33
39
|
description: 'eval() with dynamic input can execute arbitrary code',
|
|
34
40
|
severity: 'critical',
|
|
41
|
+
tier: 'free',
|
|
35
42
|
languages: ['javascript', 'typescript', 'python'],
|
|
36
43
|
astMatcher: 'eval-usage',
|
|
37
44
|
fix: 'Avoid eval() entirely or use safer alternatives like JSON.parse()',
|
|
@@ -41,6 +48,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
41
48
|
name: 'Command Injection Vulnerability',
|
|
42
49
|
description: 'User input passed to shell commands can allow arbitrary command execution',
|
|
43
50
|
severity: 'critical',
|
|
51
|
+
tier: 'free',
|
|
44
52
|
languages: ['javascript', 'typescript', 'python'],
|
|
45
53
|
patterns: [
|
|
46
54
|
/child_process.*exec\s*\([^)]*\$\{/,
|
|
@@ -59,6 +67,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
59
67
|
name: 'Insecure Deserialization',
|
|
60
68
|
description: 'Deserializing untrusted data can lead to remote code execution',
|
|
61
69
|
severity: 'critical',
|
|
70
|
+
tier: 'free',
|
|
62
71
|
languages: ['javascript', 'typescript', 'python'],
|
|
63
72
|
patterns: [
|
|
64
73
|
/pickle\.loads?\s*\(/,
|
|
@@ -71,12 +80,13 @@ export const securityRules: SecurityRule[] = [
|
|
|
71
80
|
fix: 'Use safe deserialization methods. For Python use yaml.safe_load(). Avoid pickle with untrusted data',
|
|
72
81
|
},
|
|
73
82
|
|
|
74
|
-
// HIGH
|
|
83
|
+
// HIGH (Pro - framework-specific)
|
|
75
84
|
{
|
|
76
85
|
id: 'missing-auth-route',
|
|
77
86
|
name: 'Missing Authentication on API Route',
|
|
78
87
|
description: 'API routes without authentication checks can be accessed by anyone',
|
|
79
88
|
severity: 'high',
|
|
89
|
+
tier: 'pro',
|
|
80
90
|
languages: ['javascript', 'typescript'],
|
|
81
91
|
astMatcher: 'missing-auth',
|
|
82
92
|
fix: 'Add authentication middleware or check session/token at route start',
|
|
@@ -86,6 +96,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
86
96
|
name: 'XSS via innerHTML/dangerouslySetInnerHTML',
|
|
87
97
|
description: 'Setting innerHTML with user data can execute malicious scripts',
|
|
88
98
|
severity: 'high',
|
|
99
|
+
tier: 'free',
|
|
89
100
|
languages: ['javascript', 'typescript'],
|
|
90
101
|
astMatcher: 'xss-innerhtml',
|
|
91
102
|
fix: 'Use textContent instead of innerHTML, or sanitize with DOMPurify',
|
|
@@ -95,6 +106,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
95
106
|
name: 'Secrets in localStorage/sessionStorage',
|
|
96
107
|
description: 'Storing sensitive data in browser storage exposes it to XSS attacks',
|
|
97
108
|
severity: 'high',
|
|
109
|
+
tier: 'free',
|
|
98
110
|
languages: ['javascript', 'typescript'],
|
|
99
111
|
patterns: [
|
|
100
112
|
/localStorage\.setItem\s*\(\s*['"`](?:token|jwt|auth|session|api[_-]?key|secret|password|credential)/i,
|
|
@@ -107,6 +119,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
107
119
|
name: 'Supabase Without RLS',
|
|
108
120
|
description: 'Direct table access without Row Level Security allows unauthorized data access',
|
|
109
121
|
severity: 'high',
|
|
122
|
+
tier: 'pro',
|
|
110
123
|
languages: ['javascript', 'typescript'],
|
|
111
124
|
patterns: [
|
|
112
125
|
/\.from\s*\(\s*['"`][^'"`]+['"`]\s*\)\.(?:select|insert|update|delete)/,
|
|
@@ -119,6 +132,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
119
132
|
name: 'Firebase Without Security Rules',
|
|
120
133
|
description: 'Firebase operations without proper security rules can expose data',
|
|
121
134
|
severity: 'high',
|
|
135
|
+
tier: 'pro',
|
|
122
136
|
languages: ['javascript', 'typescript'],
|
|
123
137
|
patterns: [
|
|
124
138
|
/firestore\(\)\.collection\s*\(\s*['"`][^'"`]+['"`]\s*\)/,
|
|
@@ -131,6 +145,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
131
145
|
name: 'Potential IDOR Vulnerability',
|
|
132
146
|
description: 'Direct object references without ownership check allow unauthorized access',
|
|
133
147
|
severity: 'high',
|
|
148
|
+
tier: 'free',
|
|
134
149
|
languages: ['javascript', 'typescript'],
|
|
135
150
|
astMatcher: 'idor',
|
|
136
151
|
fix: 'Always verify the requesting user owns or has access to the resource',
|
|
@@ -140,6 +155,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
140
155
|
name: 'Path Traversal Vulnerability',
|
|
141
156
|
description: 'User input in file paths can allow access to arbitrary files',
|
|
142
157
|
severity: 'high',
|
|
158
|
+
tier: 'free',
|
|
143
159
|
languages: ['javascript', 'typescript', 'python'],
|
|
144
160
|
patterns: [
|
|
145
161
|
/(?:readFile|writeFile|readFileSync|writeFileSync|createReadStream|createWriteStream)\s*\([^)]*(?:req\.|params\.|query\.|body\.|\$\{)/,
|
|
@@ -155,6 +171,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
155
171
|
name: 'Server-Side Request Forgery (SSRF)',
|
|
156
172
|
description: 'User-controlled URLs can be used to access internal services',
|
|
157
173
|
severity: 'high',
|
|
174
|
+
tier: 'free',
|
|
158
175
|
languages: ['javascript', 'typescript', 'python'],
|
|
159
176
|
patterns: [
|
|
160
177
|
/(?:fetch|axios\.get|axios\.post|request|got|node-fetch)\s*\([^)]*(?:req\.|params\.|query\.|body\.|\$\{)/,
|
|
@@ -169,6 +186,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
169
186
|
name: 'Open Redirect Vulnerability',
|
|
170
187
|
description: 'Redirecting to user-supplied URLs can be used for phishing attacks',
|
|
171
188
|
severity: 'high',
|
|
189
|
+
tier: 'free',
|
|
172
190
|
languages: ['javascript', 'typescript', 'python'],
|
|
173
191
|
patterns: [
|
|
174
192
|
/res\.redirect\s*\([^)]*(?:req\.|params\.|query\.|body\.)/,
|
|
@@ -185,6 +203,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
185
203
|
name: 'Insecure Cookie Configuration',
|
|
186
204
|
description: 'Cookies without security flags are vulnerable to theft and CSRF',
|
|
187
205
|
severity: 'high',
|
|
206
|
+
tier: 'free',
|
|
188
207
|
languages: ['javascript', 'typescript', 'python'],
|
|
189
208
|
patterns: [
|
|
190
209
|
/^\s*res\.cookie\s*\(\s*['"`](?:token|session|auth|jwt)[^'"]*['"`]\s*,\s*\w+\s*\)/im,
|
|
@@ -198,6 +217,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
198
217
|
name: 'Missing CSRF Protection',
|
|
199
218
|
description: 'Forms without CSRF tokens can be exploited by malicious sites',
|
|
200
219
|
severity: 'high',
|
|
220
|
+
tier: 'free',
|
|
201
221
|
languages: ['javascript', 'typescript', 'python'],
|
|
202
222
|
patterns: [
|
|
203
223
|
/<form[^>]+method\s*=\s*['"`]post['"`][^>]*>(?![^<]{0,200}csrf)/i,
|
|
@@ -206,12 +226,13 @@ export const securityRules: SecurityRule[] = [
|
|
|
206
226
|
fix: 'Implement CSRF tokens using csurf (Express) or Django/Flask CSRF middleware',
|
|
207
227
|
},
|
|
208
228
|
|
|
209
|
-
// MEDIUM
|
|
229
|
+
// MEDIUM (Free tier)
|
|
210
230
|
{
|
|
211
231
|
id: 'permissive-cors',
|
|
212
232
|
name: 'Permissive CORS Configuration',
|
|
213
233
|
description: 'Allowing all origins can enable CSRF attacks from any website',
|
|
214
234
|
severity: 'medium',
|
|
235
|
+
tier: 'free',
|
|
215
236
|
languages: ['javascript', 'typescript', 'python'],
|
|
216
237
|
patterns: [
|
|
217
238
|
/Access-Control-Allow-Origin['"`:]\s*['"`]\*['"`]/,
|
|
@@ -225,6 +246,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
225
246
|
name: 'HTTP Instead of HTTPS',
|
|
226
247
|
description: 'Unencrypted HTTP connections can be intercepted',
|
|
227
248
|
severity: 'medium',
|
|
249
|
+
tier: 'free',
|
|
228
250
|
languages: ['javascript', 'typescript', 'python'],
|
|
229
251
|
patterns: [
|
|
230
252
|
/['"`]http:\/\/(?!localhost|127\.0\.0\.1|0\.0\.0\.0)[^'"`]+['"`]/,
|
|
@@ -236,6 +258,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
236
258
|
name: 'Weak Password Requirements',
|
|
237
259
|
description: 'Password validation that allows weak passwords',
|
|
238
260
|
severity: 'medium',
|
|
261
|
+
tier: 'free',
|
|
239
262
|
languages: ['javascript', 'typescript', 'python'],
|
|
240
263
|
patterns: [
|
|
241
264
|
/password\.length\s*(?:>=?|>)\s*[1-5](?!\d)/,
|
|
@@ -249,6 +272,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
249
272
|
name: 'Hardcoded IP Address',
|
|
250
273
|
description: 'Hardcoded IP addresses make configuration inflexible and may expose internal infrastructure',
|
|
251
274
|
severity: 'medium',
|
|
275
|
+
tier: 'free',
|
|
252
276
|
languages: ['javascript', 'typescript', 'python'],
|
|
253
277
|
patterns: [
|
|
254
278
|
/['"`](?:10\.\d{1,3}\.\d{1,3}\.\d{1,3})['"`]/,
|
|
@@ -263,6 +287,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
263
287
|
name: 'XML External Entity (XXE) Injection',
|
|
264
288
|
description: 'XML parsers with external entities enabled can leak files or perform SSRF',
|
|
265
289
|
severity: 'medium',
|
|
290
|
+
tier: 'free',
|
|
266
291
|
languages: ['javascript', 'typescript', 'python'],
|
|
267
292
|
patterns: [
|
|
268
293
|
/xml2js/,
|
|
@@ -281,6 +306,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
281
306
|
name: 'JWT None Algorithm Vulnerability',
|
|
282
307
|
description: 'Accepting "none" algorithm in JWT allows token forgery',
|
|
283
308
|
severity: 'medium',
|
|
309
|
+
tier: 'free',
|
|
284
310
|
languages: ['javascript', 'typescript', 'python'],
|
|
285
311
|
patterns: [
|
|
286
312
|
/algorithms\s*:\s*\[[^\]]*['"`]none['"`]/i,
|
|
@@ -291,12 +317,13 @@ export const securityRules: SecurityRule[] = [
|
|
|
291
317
|
fix: 'Always specify allowed algorithms explicitly and never include "none"',
|
|
292
318
|
},
|
|
293
319
|
|
|
294
|
-
// LOW
|
|
320
|
+
// LOW (Free tier)
|
|
295
321
|
{
|
|
296
322
|
id: 'verbose-errors',
|
|
297
323
|
name: 'Verbose Error Messages to Client',
|
|
298
324
|
description: 'Detailed error messages can leak implementation details to attackers',
|
|
299
325
|
severity: 'low',
|
|
326
|
+
tier: 'free',
|
|
300
327
|
languages: ['javascript', 'typescript'],
|
|
301
328
|
patterns: [
|
|
302
329
|
/res\.(?:json|send)\s*\(\s*(?:err|error)(?:\.message|\.stack)?/,
|
|
@@ -309,6 +336,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
309
336
|
name: 'Missing Rate Limiting',
|
|
310
337
|
description: 'Auth endpoints without rate limiting are vulnerable to brute force attacks',
|
|
311
338
|
severity: 'low',
|
|
339
|
+
tier: 'free',
|
|
312
340
|
languages: ['javascript', 'typescript'],
|
|
313
341
|
patterns: [
|
|
314
342
|
/app\.post\s*\(\s*['"`]\/(?:login|signin|auth\/login|api\/login)['"`]\s*,\s*(?:async\s*)?\(/,
|
|
@@ -323,6 +351,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
323
351
|
name: 'Logging Sensitive Data',
|
|
324
352
|
description: 'Logging sensitive information can expose it in log files',
|
|
325
353
|
severity: 'low',
|
|
354
|
+
tier: 'free',
|
|
326
355
|
languages: ['javascript', 'typescript', 'python'],
|
|
327
356
|
patterns: [
|
|
328
357
|
/console\.log\s*\(\s*(?:password|secret|apiKey|token|credential|accessToken|refreshToken)\s*[,)]/i,
|
|
@@ -338,6 +367,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
338
367
|
name: 'Debug Mode Enabled in Production',
|
|
339
368
|
description: 'Debug mode can expose sensitive information and stack traces',
|
|
340
369
|
severity: 'low',
|
|
370
|
+
tier: 'free',
|
|
341
371
|
languages: ['javascript', 'typescript', 'python'],
|
|
342
372
|
patterns: [
|
|
343
373
|
/DEBUG\s*=\s*True/,
|
|
@@ -352,6 +382,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
352
382
|
name: 'Potential Prototype Pollution',
|
|
353
383
|
description: 'Merging user input into objects can allow prototype pollution attacks',
|
|
354
384
|
severity: 'low',
|
|
385
|
+
tier: 'free',
|
|
355
386
|
languages: ['javascript', 'typescript'],
|
|
356
387
|
patterns: [
|
|
357
388
|
/Object\.assign\s*\(\s*\{\}\s*,[^)]*(?:req\.|body\.|params\.|query\.)/,
|
|
@@ -363,7 +394,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
363
394
|
},
|
|
364
395
|
|
|
365
396
|
// ============================================
|
|
366
|
-
//
|
|
397
|
+
// PRO TIER RULES - Framework-specific
|
|
367
398
|
// ============================================
|
|
368
399
|
|
|
369
400
|
// --- Next.js ---
|
|
@@ -372,6 +403,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
372
403
|
name: 'Next.js Server Action Without Auth',
|
|
373
404
|
description: 'Server actions are public endpoints and need authentication checks',
|
|
374
405
|
severity: 'high',
|
|
406
|
+
tier: 'pro',
|
|
375
407
|
languages: ['javascript', 'typescript'],
|
|
376
408
|
patterns: [
|
|
377
409
|
/['"`]use server['"`]\s*;?\s*(?:export\s+)?(?:async\s+)?function\s+\w+\s*\([^)]*\)\s*\{(?![^}]*(?:auth|session|getServerSession|currentUser))/,
|
|
@@ -383,6 +415,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
383
415
|
name: 'Next.js API Route Without Auth Check',
|
|
384
416
|
description: 'API routes in Next.js are public by default and need explicit auth',
|
|
385
417
|
severity: 'high',
|
|
418
|
+
tier: 'pro',
|
|
386
419
|
languages: ['javascript', 'typescript'],
|
|
387
420
|
patterns: [
|
|
388
421
|
/export\s+(?:default\s+)?(?:async\s+)?function\s+(?:GET|POST|PUT|DELETE|PATCH)\s*\([^)]*\)\s*\{(?![^}]{0,500}(?:getServerSession|auth|getToken|verifyToken|currentUser))/,
|
|
@@ -394,6 +427,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
394
427
|
name: 'Next.js dangerouslySetInnerHTML with User Data',
|
|
395
428
|
description: 'Using dangerouslySetInnerHTML with dynamic data can cause XSS',
|
|
396
429
|
severity: 'high',
|
|
430
|
+
tier: 'pro',
|
|
397
431
|
languages: ['javascript', 'typescript'],
|
|
398
432
|
patterns: [
|
|
399
433
|
/dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(?!['"`])/,
|
|
@@ -405,6 +439,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
405
439
|
name: 'Next.js Private Env Exposed to Client',
|
|
406
440
|
description: 'Environment variables without NEXT_PUBLIC_ prefix should not be in client code',
|
|
407
441
|
severity: 'high',
|
|
442
|
+
tier: 'pro',
|
|
408
443
|
languages: ['javascript', 'typescript'],
|
|
409
444
|
patterns: [
|
|
410
445
|
/['"`]use client['"`][\s\S]*process\.env\.(?!NEXT_PUBLIC_)[A-Z_]+/,
|
|
@@ -418,6 +453,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
418
453
|
name: 'Django DEBUG=True in Production',
|
|
419
454
|
description: 'Debug mode exposes sensitive information and should never be enabled in production',
|
|
420
455
|
severity: 'critical',
|
|
456
|
+
tier: 'pro',
|
|
421
457
|
languages: ['python'],
|
|
422
458
|
patterns: [
|
|
423
459
|
/DEBUG\s*=\s*True/,
|
|
@@ -429,6 +465,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
429
465
|
name: 'Django SECRET_KEY Hardcoded',
|
|
430
466
|
description: 'Hardcoded SECRET_KEY can be extracted and used to forge sessions',
|
|
431
467
|
severity: 'critical',
|
|
468
|
+
tier: 'pro',
|
|
432
469
|
languages: ['python'],
|
|
433
470
|
patterns: [
|
|
434
471
|
/SECRET_KEY\s*=\s*['"`][^'"`]{20,}['"`]/,
|
|
@@ -440,6 +477,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
440
477
|
name: 'Django Raw SQL Query',
|
|
441
478
|
description: 'Raw SQL queries with string formatting are vulnerable to SQL injection',
|
|
442
479
|
severity: 'critical',
|
|
480
|
+
tier: 'pro',
|
|
443
481
|
languages: ['python'],
|
|
444
482
|
patterns: [
|
|
445
483
|
/\.raw\s*\(\s*f['"`]/,
|
|
@@ -454,6 +492,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
454
492
|
name: 'Django CSRF Exemption',
|
|
455
493
|
description: 'Disabling CSRF protection exposes the endpoint to cross-site attacks',
|
|
456
494
|
severity: 'high',
|
|
495
|
+
tier: 'pro',
|
|
457
496
|
languages: ['python'],
|
|
458
497
|
patterns: [
|
|
459
498
|
/@csrf_exempt/,
|
|
@@ -465,6 +504,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
465
504
|
name: 'Django ALLOWED_HOSTS Wildcard',
|
|
466
505
|
description: 'Allowing all hosts can enable host header attacks',
|
|
467
506
|
severity: 'medium',
|
|
507
|
+
tier: 'pro',
|
|
468
508
|
languages: ['python'],
|
|
469
509
|
patterns: [
|
|
470
510
|
/ALLOWED_HOSTS\s*=\s*\[\s*['"`]\*['"`]\s*\]/,
|
|
@@ -478,6 +518,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
478
518
|
name: 'FastAPI Endpoint Without Auth Dependency',
|
|
479
519
|
description: 'Sensitive endpoints should use Depends() for authentication',
|
|
480
520
|
severity: 'high',
|
|
521
|
+
tier: 'pro',
|
|
481
522
|
languages: ['python'],
|
|
482
523
|
patterns: [
|
|
483
524
|
/@app\.(?:post|put|delete|patch)\s*\(\s*['"`]\/(?:admin|user|account|settings)[^'"]*['"`]\s*\)\s*\n(?:async\s+)?def\s+\w+\s*\([^)]*\)(?![^:]*Depends)/,
|
|
@@ -489,6 +530,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
489
530
|
name: 'FastAPI CORS Allow All Origins',
|
|
490
531
|
description: 'Allowing all origins with credentials enabled is a security risk',
|
|
491
532
|
severity: 'medium',
|
|
533
|
+
tier: 'pro',
|
|
492
534
|
languages: ['python'],
|
|
493
535
|
patterns: [
|
|
494
536
|
/add_middleware\s*\(\s*CORSMiddleware[^)]*allow_origins\s*=\s*\[\s*['"`]\*['"`]\s*\]/,
|
|
@@ -502,6 +544,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
502
544
|
name: 'NestJS Controller Without Auth Guard',
|
|
503
545
|
description: 'Controllers handling sensitive data should use authentication guards',
|
|
504
546
|
severity: 'high',
|
|
547
|
+
tier: 'pro',
|
|
505
548
|
languages: ['typescript'],
|
|
506
549
|
patterns: [
|
|
507
550
|
/@Controller\s*\(\s*['"`](?:admin|user|account|settings|payment)[^'"]*['"`]\s*\)\s*\nexport\s+class\s+\w+(?![^{]*@UseGuards)/,
|
|
@@ -513,6 +556,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
513
556
|
name: 'NestJS Internal Exception Exposed',
|
|
514
557
|
description: 'Throwing raw errors exposes internal details to clients',
|
|
515
558
|
severity: 'low',
|
|
559
|
+
tier: 'pro',
|
|
516
560
|
languages: ['typescript'],
|
|
517
561
|
patterns: [
|
|
518
562
|
/throw\s+new\s+(?:Error|InternalServerErrorException)\s*\(\s*(?:err|error)\.message/,
|
|
@@ -526,6 +570,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
526
570
|
name: 'React href with javascript: Protocol',
|
|
527
571
|
description: 'javascript: URLs in href can execute arbitrary code',
|
|
528
572
|
severity: 'high',
|
|
573
|
+
tier: 'pro',
|
|
529
574
|
languages: ['javascript', 'typescript'],
|
|
530
575
|
patterns: [
|
|
531
576
|
/href\s*=\s*\{[^}]*['"`]javascript:/,
|
|
@@ -538,6 +583,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
538
583
|
name: 'React URL Parameters in Dangerous Context',
|
|
539
584
|
description: 'URL parameters used in dangerous contexts can cause XSS',
|
|
540
585
|
severity: 'high',
|
|
586
|
+
tier: 'pro',
|
|
541
587
|
languages: ['javascript', 'typescript'],
|
|
542
588
|
patterns: [
|
|
543
589
|
/useSearchParams\s*\(\s*\)[\s\S]*dangerouslySetInnerHTML/,
|
|
@@ -552,6 +598,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
552
598
|
name: 'Express Missing Security Headers (Helmet)',
|
|
553
599
|
description: 'Express apps should use Helmet for security headers',
|
|
554
600
|
severity: 'medium',
|
|
601
|
+
tier: 'pro',
|
|
555
602
|
languages: ['javascript', 'typescript'],
|
|
556
603
|
patterns: [
|
|
557
604
|
/express\s*\(\s*\)(?![^;]*helmet)/,
|
|
@@ -563,6 +610,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
563
610
|
name: 'Express Body Parser Without Size Limit',
|
|
564
611
|
description: 'Unlimited body size can lead to denial of service attacks',
|
|
565
612
|
severity: 'medium',
|
|
613
|
+
tier: 'pro',
|
|
566
614
|
languages: ['javascript', 'typescript'],
|
|
567
615
|
patterns: [
|
|
568
616
|
/express\.json\s*\(\s*\)/,
|
|
@@ -575,6 +623,7 @@ export const securityRules: SecurityRule[] = [
|
|
|
575
623
|
name: 'Express Session Insecure Configuration',
|
|
576
624
|
description: 'Session cookies should be secure and httpOnly',
|
|
577
625
|
severity: 'high',
|
|
626
|
+
tier: 'pro',
|
|
578
627
|
languages: ['javascript', 'typescript'],
|
|
579
628
|
patterns: [
|
|
580
629
|
/session\s*\(\s*\{[^}]*secret\s*:[^}]*\}\s*\)(?![^)]*(?:secure|httpOnly))/,
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export type Severity = 'critical' | 'high' | 'medium' | 'low';
|
|
2
|
+
export type Tier = 'free' | 'pro';
|
|
2
3
|
|
|
3
4
|
export interface SecurityRule {
|
|
4
5
|
id: string;
|
|
5
6
|
name: string;
|
|
6
7
|
description: string;
|
|
7
8
|
severity: Severity;
|
|
9
|
+
tier: Tier;
|
|
8
10
|
languages: ('javascript' | 'typescript' | 'python')[];
|
|
9
11
|
patterns?: RegExp[];
|
|
10
12
|
astMatcher?: string;
|
|
@@ -18,6 +20,7 @@ export interface Finding {
|
|
|
18
20
|
column: number;
|
|
19
21
|
code: string;
|
|
20
22
|
message: string;
|
|
23
|
+
isRestricted: boolean; // true if user on free tier and rule is 'pro'
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export interface ScanResult {
|