@indicated/vibeguard 1.0.1 → 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.
Files changed (48) hide show
  1. package/PROGRESS.md +42 -13
  2. package/dist/api/license.d.ts +14 -2
  3. package/dist/api/license.d.ts.map +1 -1
  4. package/dist/api/license.js +46 -13
  5. package/dist/api/license.js.map +1 -1
  6. package/dist/cli/commands/scan.d.ts.map +1 -1
  7. package/dist/cli/commands/scan.js +7 -2
  8. package/dist/cli/commands/scan.js.map +1 -1
  9. package/dist/cli/commands/upgrade.d.ts +3 -0
  10. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  11. package/dist/cli/commands/upgrade.js +70 -0
  12. package/dist/cli/commands/upgrade.js.map +1 -0
  13. package/dist/cli/index.js +2 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/output.d.ts +3 -2
  16. package/dist/cli/output.d.ts.map +1 -1
  17. package/dist/cli/output.js +27 -4
  18. package/dist/cli/output.js.map +1 -1
  19. package/dist/scanner/index.d.ts +4 -1
  20. package/dist/scanner/index.d.ts.map +1 -1
  21. package/dist/scanner/index.js +15 -2
  22. package/dist/scanner/index.js.map +1 -1
  23. package/dist/scanner/parsers/javascript.d.ts.map +1 -1
  24. package/dist/scanner/parsers/javascript.js +6 -0
  25. package/dist/scanner/parsers/javascript.js.map +1 -1
  26. package/dist/scanner/parsers/python.d.ts.map +1 -1
  27. package/dist/scanner/parsers/python.js +2 -0
  28. package/dist/scanner/parsers/python.js.map +1 -1
  29. package/dist/scanner/rules/definitions.d.ts.map +1 -1
  30. package/dist/scanner/rules/definitions.js +52 -4
  31. package/dist/scanner/rules/definitions.js.map +1 -1
  32. package/dist/scanner/rules/matcher.d.ts.map +1 -1
  33. package/dist/scanner/rules/matcher.js +1 -0
  34. package/dist/scanner/rules/matcher.js.map +1 -1
  35. package/dist/types.d.ts +3 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/api/license.ts +50 -15
  39. package/src/cli/commands/scan.ts +8 -2
  40. package/src/cli/commands/upgrade.ts +76 -0
  41. package/src/cli/index.ts +2 -0
  42. package/src/cli/output.ts +28 -5
  43. package/src/scanner/index.ts +19 -3
  44. package/src/scanner/parsers/javascript.ts +6 -0
  45. package/src/scanner/parsers/python.ts +2 -0
  46. package/src/scanner/rules/definitions.ts +53 -4
  47. package/src/scanner/rules/matcher.ts +1 -0
  48. 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
- // FRAMEWORK-SPECIFIC RULES
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))/,
@@ -35,6 +35,7 @@ export function matchPatterns(
35
35
  column,
36
36
  code: context.lines[lineNumber - 1] || '',
37
37
  message: rule.description,
38
+ isRestricted: false,
38
39
  });
39
40
 
40
41
  // Prevent infinite loops on zero-width matches
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 {