@indicated/vibeguard 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/.claude/settings.local.json +5 -0
  2. package/.github/workflows/ci.yml +65 -0
  3. package/.github/workflows/release.yml +85 -0
  4. package/PROGRESS.md +192 -0
  5. package/README.md +183 -0
  6. package/dist/api/license.d.ts +13 -0
  7. package/dist/api/license.d.ts.map +1 -0
  8. package/dist/api/license.js +138 -0
  9. package/dist/api/license.js.map +1 -0
  10. package/dist/api/rules.d.ts +13 -0
  11. package/dist/api/rules.d.ts.map +1 -0
  12. package/dist/api/rules.js +57 -0
  13. package/dist/api/rules.js.map +1 -0
  14. package/dist/cli/commands/init.d.ts +3 -0
  15. package/dist/cli/commands/init.d.ts.map +1 -0
  16. package/dist/cli/commands/init.js +145 -0
  17. package/dist/cli/commands/init.js.map +1 -0
  18. package/dist/cli/commands/login.d.ts +4 -0
  19. package/dist/cli/commands/login.d.ts.map +1 -0
  20. package/dist/cli/commands/login.js +121 -0
  21. package/dist/cli/commands/login.js.map +1 -0
  22. package/dist/cli/commands/mcp.d.ts +3 -0
  23. package/dist/cli/commands/mcp.d.ts.map +1 -0
  24. package/dist/cli/commands/mcp.js +14 -0
  25. package/dist/cli/commands/mcp.js.map +1 -0
  26. package/dist/cli/commands/rules.d.ts +3 -0
  27. package/dist/cli/commands/rules.d.ts.map +1 -0
  28. package/dist/cli/commands/rules.js +52 -0
  29. package/dist/cli/commands/rules.js.map +1 -0
  30. package/dist/cli/commands/scan.d.ts +3 -0
  31. package/dist/cli/commands/scan.d.ts.map +1 -0
  32. package/dist/cli/commands/scan.js +114 -0
  33. package/dist/cli/commands/scan.js.map +1 -0
  34. package/dist/cli/config.d.ts +4 -0
  35. package/dist/cli/config.d.ts.map +1 -0
  36. package/dist/cli/config.js +88 -0
  37. package/dist/cli/config.js.map +1 -0
  38. package/dist/cli/index.d.ts +3 -0
  39. package/dist/cli/index.d.ts.map +1 -0
  40. package/dist/cli/index.js +25 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/cli/output.d.ts +15 -0
  43. package/dist/cli/output.d.ts.map +1 -0
  44. package/dist/cli/output.js +152 -0
  45. package/dist/cli/output.js.map +1 -0
  46. package/dist/mcp/server.d.ts +2 -0
  47. package/dist/mcp/server.d.ts.map +1 -0
  48. package/dist/mcp/server.js +188 -0
  49. package/dist/mcp/server.js.map +1 -0
  50. package/dist/scanner/index.d.ts +15 -0
  51. package/dist/scanner/index.d.ts.map +1 -0
  52. package/dist/scanner/index.js +207 -0
  53. package/dist/scanner/index.js.map +1 -0
  54. package/dist/scanner/parsers/javascript.d.ts +12 -0
  55. package/dist/scanner/parsers/javascript.d.ts.map +1 -0
  56. package/dist/scanner/parsers/javascript.js +266 -0
  57. package/dist/scanner/parsers/javascript.js.map +1 -0
  58. package/dist/scanner/parsers/python.d.ts +3 -0
  59. package/dist/scanner/parsers/python.d.ts.map +1 -0
  60. package/dist/scanner/parsers/python.js +108 -0
  61. package/dist/scanner/parsers/python.js.map +1 -0
  62. package/dist/scanner/rules/definitions.d.ts +5 -0
  63. package/dist/scanner/rules/definitions.d.ts.map +1 -0
  64. package/dist/scanner/rules/definitions.js +584 -0
  65. package/dist/scanner/rules/definitions.js.map +1 -0
  66. package/dist/scanner/rules/loader.d.ts +8 -0
  67. package/dist/scanner/rules/loader.d.ts.map +1 -0
  68. package/dist/scanner/rules/loader.js +45 -0
  69. package/dist/scanner/rules/loader.js.map +1 -0
  70. package/dist/scanner/rules/matcher.d.ts +11 -0
  71. package/dist/scanner/rules/matcher.d.ts.map +1 -0
  72. package/dist/scanner/rules/matcher.js +53 -0
  73. package/dist/scanner/rules/matcher.js.map +1 -0
  74. package/dist/types.d.ts +33 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +3 -0
  77. package/dist/types.js.map +1 -0
  78. package/package.json +48 -0
  79. package/src/api/license.ts +120 -0
  80. package/src/api/rules.ts +70 -0
  81. package/src/cli/commands/init.ts +123 -0
  82. package/src/cli/commands/login.ts +92 -0
  83. package/src/cli/commands/mcp.ts +12 -0
  84. package/src/cli/commands/rules.ts +58 -0
  85. package/src/cli/commands/scan.ts +94 -0
  86. package/src/cli/config.ts +54 -0
  87. package/src/cli/index.ts +28 -0
  88. package/src/cli/output.ts +159 -0
  89. package/src/mcp/server.ts +195 -0
  90. package/src/scanner/index.ts +195 -0
  91. package/src/scanner/parsers/javascript.ts +285 -0
  92. package/src/scanner/parsers/python.ts +126 -0
  93. package/src/scanner/rules/definitions.ts +592 -0
  94. package/src/scanner/rules/loader.ts +59 -0
  95. package/src/scanner/rules/matcher.ts +68 -0
  96. package/src/types.ts +36 -0
  97. package/test-samples/secure.js +52 -0
  98. package/test-samples/vulnerable.js +56 -0
  99. package/test-samples/vulnerable.py +39 -0
  100. package/tests/helpers.ts +43 -0
  101. package/tests/rules/critical.test.ts +186 -0
  102. package/tests/rules/definitions.test.ts +167 -0
  103. package/tests/rules/high.test.ts +377 -0
  104. package/tests/rules/low.test.ts +172 -0
  105. package/tests/rules/medium.test.ts +224 -0
  106. package/tests/scanner/scanner.test.ts +161 -0
  107. package/tsconfig.json +19 -0
  108. package/vibe-coding-security-checklist.md +245 -0
  109. package/vitest.config.ts +15 -0
@@ -0,0 +1,584 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.securityRules = void 0;
4
+ exports.getRuleById = getRuleById;
5
+ exports.getRulesBySeverity = getRulesBySeverity;
6
+ exports.securityRules = [
7
+ // CRITICAL
8
+ {
9
+ id: 'hardcoded-secret',
10
+ name: 'Hardcoded API Key/Secret',
11
+ description: 'Hardcoded secrets can be extracted from source code and used maliciously',
12
+ severity: 'critical',
13
+ languages: ['javascript', 'typescript', 'python'],
14
+ patterns: [
15
+ /(['"`])(?:sk-[a-zA-Z0-9]{20,})\1/,
16
+ /(['"`])(?:api[_-]?key|apikey|secret[_-]?key|secretkey|password|passwd|pwd)\s*[=:]\s*\1[^'"`\n]{8,}\1/i,
17
+ /(['"`])(?:ghp_[a-zA-Z0-9]{36})\1/,
18
+ /(['"`])(?:xox[baprs]-[a-zA-Z0-9-]{10,})\1/,
19
+ /(['"`])(?:AKIA[0-9A-Z]{16})\1/,
20
+ /(['"`])(?:eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*)\1/,
21
+ ],
22
+ fix: 'Move secrets to environment variables and use process.env',
23
+ },
24
+ {
25
+ id: 'sql-injection',
26
+ name: 'SQL Injection Vulnerability',
27
+ description: 'User input directly concatenated into SQL queries can allow attackers to execute arbitrary SQL',
28
+ severity: 'critical',
29
+ languages: ['javascript', 'typescript', 'python'],
30
+ astMatcher: 'sql-injection',
31
+ fix: 'Use parameterized queries or prepared statements',
32
+ },
33
+ {
34
+ id: 'eval-usage',
35
+ name: 'Dangerous eval() Usage',
36
+ description: 'eval() with dynamic input can execute arbitrary code',
37
+ severity: 'critical',
38
+ languages: ['javascript', 'typescript', 'python'],
39
+ astMatcher: 'eval-usage',
40
+ fix: 'Avoid eval() entirely or use safer alternatives like JSON.parse()',
41
+ },
42
+ {
43
+ id: 'command-injection',
44
+ name: 'Command Injection Vulnerability',
45
+ description: 'User input passed to shell commands can allow arbitrary command execution',
46
+ severity: 'critical',
47
+ languages: ['javascript', 'typescript', 'python'],
48
+ patterns: [
49
+ /child_process.*exec\s*\([^)]*\$\{/,
50
+ /child_process.*exec\s*\([^)]*\+/,
51
+ /exec\s*\(\s*['"`][^'"`]*\$\{/,
52
+ /execSync\s*\(\s*['"`][^'"`]*\$\{/,
53
+ /spawn\s*\(\s*['"`][^'"`]*\$\{/,
54
+ /subprocess\.(?:call|run|Popen)\s*\([^)]*(?:shell\s*=\s*True|f['"`])/,
55
+ /os\.system\s*\(\s*f?['"`]/,
56
+ /os\.popen\s*\(\s*f?['"`]/,
57
+ ],
58
+ fix: 'Never pass user input to shell commands. Use parameterized APIs or escape input properly',
59
+ },
60
+ {
61
+ id: 'insecure-deserialization',
62
+ name: 'Insecure Deserialization',
63
+ description: 'Deserializing untrusted data can lead to remote code execution',
64
+ severity: 'critical',
65
+ languages: ['javascript', 'typescript', 'python'],
66
+ patterns: [
67
+ /pickle\.loads?\s*\(/,
68
+ /yaml\.(?:load|unsafe_load)\s*\([^)]*(?!Loader)/,
69
+ /eval\s*\(\s*JSON\.parse/,
70
+ /serialize-javascript/,
71
+ /node-serialize/,
72
+ /unserialize\s*\(/,
73
+ ],
74
+ fix: 'Use safe deserialization methods. For Python use yaml.safe_load(). Avoid pickle with untrusted data',
75
+ },
76
+ // HIGH
77
+ {
78
+ id: 'missing-auth-route',
79
+ name: 'Missing Authentication on API Route',
80
+ description: 'API routes without authentication checks can be accessed by anyone',
81
+ severity: 'high',
82
+ languages: ['javascript', 'typescript'],
83
+ astMatcher: 'missing-auth',
84
+ fix: 'Add authentication middleware or check session/token at route start',
85
+ },
86
+ {
87
+ id: 'xss-innerhtml',
88
+ name: 'XSS via innerHTML/dangerouslySetInnerHTML',
89
+ description: 'Setting innerHTML with user data can execute malicious scripts',
90
+ severity: 'high',
91
+ languages: ['javascript', 'typescript'],
92
+ astMatcher: 'xss-innerhtml',
93
+ fix: 'Use textContent instead of innerHTML, or sanitize with DOMPurify',
94
+ },
95
+ {
96
+ id: 'secrets-localstorage',
97
+ name: 'Secrets in localStorage/sessionStorage',
98
+ description: 'Storing sensitive data in browser storage exposes it to XSS attacks',
99
+ severity: 'high',
100
+ languages: ['javascript', 'typescript'],
101
+ patterns: [
102
+ /localStorage\.setItem\s*\(\s*['"`](?:token|jwt|auth|session|api[_-]?key|secret|password|credential)/i,
103
+ /sessionStorage\.setItem\s*\(\s*['"`](?:token|jwt|auth|session|api[_-]?key|secret|password|credential)/i,
104
+ ],
105
+ fix: 'Use httpOnly cookies for sensitive tokens, or encrypt before storage',
106
+ },
107
+ {
108
+ id: 'supabase-no-rls',
109
+ name: 'Supabase Without RLS',
110
+ description: 'Direct table access without Row Level Security allows unauthorized data access',
111
+ severity: 'high',
112
+ languages: ['javascript', 'typescript'],
113
+ patterns: [
114
+ /\.from\s*\(\s*['"`][^'"`]+['"`]\s*\)\.(?:select|insert|update|delete)/,
115
+ ],
116
+ astMatcher: 'supabase-no-rls',
117
+ fix: 'Enable Row Level Security on Supabase tables and add policies',
118
+ },
119
+ {
120
+ id: 'firebase-no-rules',
121
+ name: 'Firebase Without Security Rules',
122
+ description: 'Firebase operations without proper security rules can expose data',
123
+ severity: 'high',
124
+ languages: ['javascript', 'typescript'],
125
+ patterns: [
126
+ /firestore\(\)\.collection\s*\(\s*['"`][^'"`]+['"`]\s*\)/,
127
+ /firebase\.database\(\)\.ref\s*\(/,
128
+ ],
129
+ fix: 'Implement Firebase Security Rules to restrict access',
130
+ },
131
+ {
132
+ id: 'idor-vulnerability',
133
+ name: 'Potential IDOR Vulnerability',
134
+ description: 'Direct object references without ownership check allow unauthorized access',
135
+ severity: 'high',
136
+ languages: ['javascript', 'typescript'],
137
+ astMatcher: 'idor',
138
+ fix: 'Always verify the requesting user owns or has access to the resource',
139
+ },
140
+ {
141
+ id: 'path-traversal',
142
+ name: 'Path Traversal Vulnerability',
143
+ description: 'User input in file paths can allow access to arbitrary files',
144
+ severity: 'high',
145
+ languages: ['javascript', 'typescript', 'python'],
146
+ patterns: [
147
+ /(?:readFile|writeFile|readFileSync|writeFileSync|createReadStream|createWriteStream)\s*\([^)]*(?:req\.|params\.|query\.|body\.|\$\{)/,
148
+ /path\.(?:join|resolve)\s*\([^)]*(?:req\.|params\.|query\.|body\.)/,
149
+ /open\s*\(\s*(?:f['"`]|request\.|params\[)/,
150
+ /\.sendFile\s*\([^)]*(?:req\.|params\.|query\.)/,
151
+ /res\.download\s*\([^)]*(?:req\.|params\.|query\.)/,
152
+ ],
153
+ fix: 'Validate and sanitize file paths. Use path.basename() and check against allowed directories',
154
+ },
155
+ {
156
+ id: 'ssrf-vulnerability',
157
+ name: 'Server-Side Request Forgery (SSRF)',
158
+ description: 'User-controlled URLs can be used to access internal services',
159
+ severity: 'high',
160
+ languages: ['javascript', 'typescript', 'python'],
161
+ patterns: [
162
+ /(?:fetch|axios\.get|axios\.post|request|got|node-fetch)\s*\([^)]*(?:req\.|params\.|query\.|body\.|\$\{)/,
163
+ /requests\.(?:get|post|put|delete)\s*\([^)]*(?:request\.|params\[|f['"`])/,
164
+ /urllib\.request\.urlopen\s*\([^)]*(?:request\.|f['"`])/,
165
+ /http\.request\s*\([^)]*(?:req\.|params\.)/,
166
+ ],
167
+ fix: 'Validate and whitelist allowed URLs/domains. Block internal IP ranges (10.x, 172.16.x, 192.168.x, 127.x)',
168
+ },
169
+ {
170
+ id: 'open-redirect',
171
+ name: 'Open Redirect Vulnerability',
172
+ description: 'Redirecting to user-supplied URLs can be used for phishing attacks',
173
+ severity: 'high',
174
+ languages: ['javascript', 'typescript', 'python'],
175
+ patterns: [
176
+ /res\.redirect\s*\([^)]*(?:req\.|params\.|query\.|body\.)/,
177
+ /response\.redirect\s*\([^)]*(?:req\.|params\.|query\.)/,
178
+ /window\.location\s*=\s*(?:params|query|searchParams)/,
179
+ /location\.href\s*=\s*(?:params|query|searchParams)/,
180
+ /redirect\s*\(\s*request\.(?:GET|POST|args)/,
181
+ /HttpResponseRedirect\s*\([^)]*request\./,
182
+ ],
183
+ fix: 'Validate redirect URLs against a whitelist of allowed domains',
184
+ },
185
+ {
186
+ id: 'insecure-cookie',
187
+ name: 'Insecure Cookie Configuration',
188
+ description: 'Cookies without security flags are vulnerable to theft and CSRF',
189
+ severity: 'high',
190
+ languages: ['javascript', 'typescript', 'python'],
191
+ patterns: [
192
+ /^\s*res\.cookie\s*\(\s*['"`](?:token|session|auth|jwt)[^'"]*['"`]\s*,\s*\w+\s*\)/im,
193
+ /^\s*document\.cookie\s*=\s*['"`](?:token|session|auth|jwt)\s*=/im,
194
+ /^\s*response\.set_cookie\s*\(\s*['"`](?:token|session|auth)[^'"]*['"`]\s*,[^)]*\)(?![^)]*httponly)/im,
195
+ ],
196
+ fix: 'Set httpOnly, secure, and sameSite flags on sensitive cookies. Note: httpOnly can only be set server-side',
197
+ },
198
+ {
199
+ id: 'missing-csrf',
200
+ name: 'Missing CSRF Protection',
201
+ description: 'Forms without CSRF tokens can be exploited by malicious sites',
202
+ severity: 'high',
203
+ languages: ['javascript', 'typescript', 'python'],
204
+ patterns: [
205
+ /<form[^>]+method\s*=\s*['"`]post['"`][^>]*>(?![^<]{0,200}csrf)/i,
206
+ /@app\.route\s*\([^)]+methods\s*=\s*\[[^\]]*['"`]POST['"`][^\]]*\]\s*\)\s*\ndef\s+\w+/,
207
+ ],
208
+ fix: 'Implement CSRF tokens using csurf (Express) or Django/Flask CSRF middleware',
209
+ },
210
+ // MEDIUM
211
+ {
212
+ id: 'permissive-cors',
213
+ name: 'Permissive CORS Configuration',
214
+ description: 'Allowing all origins can enable CSRF attacks from any website',
215
+ severity: 'medium',
216
+ languages: ['javascript', 'typescript', 'python'],
217
+ patterns: [
218
+ /Access-Control-Allow-Origin['"`:]\s*['"`]\*['"`]/,
219
+ /cors\(\s*\{\s*origin\s*:\s*['"`]\*['"`]/,
220
+ /cors\(\s*\)/,
221
+ ],
222
+ fix: 'Restrict CORS to specific trusted origins',
223
+ },
224
+ {
225
+ id: 'http-not-https',
226
+ name: 'HTTP Instead of HTTPS',
227
+ description: 'Unencrypted HTTP connections can be intercepted',
228
+ severity: 'medium',
229
+ languages: ['javascript', 'typescript', 'python'],
230
+ patterns: [
231
+ /['"`]http:\/\/(?!localhost|127\.0\.0\.1|0\.0\.0\.0)[^'"`]+['"`]/,
232
+ ],
233
+ fix: 'Use HTTPS for all external connections',
234
+ },
235
+ {
236
+ id: 'weak-password',
237
+ name: 'Weak Password Requirements',
238
+ description: 'Password validation that allows weak passwords',
239
+ severity: 'medium',
240
+ languages: ['javascript', 'typescript', 'python'],
241
+ patterns: [
242
+ /password\.length\s*(?:>=?|>)\s*[1-5](?!\d)/,
243
+ /len\(password\)\s*(?:>=?|>)\s*[1-5](?!\d)/,
244
+ /minLength\s*:\s*[1-5](?!\d)/,
245
+ ],
246
+ fix: 'Require minimum 8 characters with complexity requirements',
247
+ },
248
+ {
249
+ id: 'hardcoded-ip',
250
+ name: 'Hardcoded IP Address',
251
+ description: 'Hardcoded IP addresses make configuration inflexible and may expose internal infrastructure',
252
+ severity: 'medium',
253
+ languages: ['javascript', 'typescript', 'python'],
254
+ patterns: [
255
+ /['"`](?:10\.\d{1,3}\.\d{1,3}\.\d{1,3})['"`]/,
256
+ /['"`](?:172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3})['"`]/,
257
+ /['"`](?:192\.168\.\d{1,3}\.\d{1,3})['"`]/,
258
+ /['"`](?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})['"`](?!.*(?:localhost|example|test|0\.0\.0\.0|127\.0\.0\.1))/,
259
+ ],
260
+ fix: 'Use environment variables or configuration files for IP addresses',
261
+ },
262
+ {
263
+ id: 'xxe-vulnerability',
264
+ name: 'XML External Entity (XXE) Injection',
265
+ description: 'XML parsers with external entities enabled can leak files or perform SSRF',
266
+ severity: 'medium',
267
+ languages: ['javascript', 'typescript', 'python'],
268
+ patterns: [
269
+ /xml2js/,
270
+ /DOMParser\s*\(\s*\)/,
271
+ /parseXML/,
272
+ /etree\.parse\s*\(/,
273
+ /xml\.etree\.ElementTree/,
274
+ /minidom\.parse/,
275
+ /lxml\.etree/,
276
+ /XMLReader/,
277
+ ],
278
+ fix: 'Disable external entities and DTDs in XML parser configuration',
279
+ },
280
+ {
281
+ id: 'jwt-none-algorithm',
282
+ name: 'JWT None Algorithm Vulnerability',
283
+ description: 'Accepting "none" algorithm in JWT allows token forgery',
284
+ severity: 'medium',
285
+ languages: ['javascript', 'typescript', 'python'],
286
+ patterns: [
287
+ /algorithms\s*:\s*\[[^\]]*['"`]none['"`]/i,
288
+ /algorithm\s*=\s*['"`]none['"`]/i,
289
+ /verify\s*:\s*false/,
290
+ /ignoreExpiration\s*:\s*true/,
291
+ ],
292
+ fix: 'Always specify allowed algorithms explicitly and never include "none"',
293
+ },
294
+ // LOW
295
+ {
296
+ id: 'verbose-errors',
297
+ name: 'Verbose Error Messages to Client',
298
+ description: 'Detailed error messages can leak implementation details to attackers',
299
+ severity: 'low',
300
+ languages: ['javascript', 'typescript'],
301
+ patterns: [
302
+ /res\.(?:json|send)\s*\(\s*(?:err|error)(?:\.message|\.stack)?/,
303
+ /\.status\s*\(\s*500\s*\)\.(?:json|send)\s*\(\s*\{[^}]*(?:error|message)\s*:\s*(?:err|error)/,
304
+ ],
305
+ fix: 'Return generic error messages to clients, log details server-side',
306
+ },
307
+ {
308
+ id: 'missing-rate-limit',
309
+ name: 'Missing Rate Limiting',
310
+ description: 'Auth endpoints without rate limiting are vulnerable to brute force attacks',
311
+ severity: 'low',
312
+ languages: ['javascript', 'typescript'],
313
+ patterns: [
314
+ /app\.post\s*\(\s*['"`]\/(?:login|signin|auth\/login|api\/login)['"`]\s*,\s*(?:async\s*)?\(/,
315
+ /app\.post\s*\(\s*['"`]\/(?:register|signup|auth\/register)['"`]\s*,\s*(?:async\s*)?\(/,
316
+ /app\.post\s*\(\s*['"`]\/(?:forgot-password|reset-password|password\/reset)['"`]\s*,\s*(?:async\s*)?\(/,
317
+ ],
318
+ astMatcher: 'missing-rate-limit',
319
+ fix: 'Add rate limiting middleware (e.g., express-rate-limit)',
320
+ },
321
+ {
322
+ id: 'console-log-sensitive',
323
+ name: 'Logging Sensitive Data',
324
+ description: 'Logging sensitive information can expose it in log files',
325
+ severity: 'low',
326
+ languages: ['javascript', 'typescript', 'python'],
327
+ patterns: [
328
+ /console\.log\s*\(\s*(?:password|secret|apiKey|token|credential|accessToken|refreshToken)\s*[,)]/i,
329
+ /console\.log\s*\([^)]*,\s*(?:password|secret|apiKey|token|credential)\s*[,)]/i,
330
+ /print\s*\(\s*(?:password|secret|api_key|token|credential)\s*[,)]/i,
331
+ /print\s*\(\s*f?['"`][^'"]*\{(?:password|secret|token|credential)\}/i,
332
+ /logger\.(?:info|debug|log)\s*\(\s*(?:password|secret|token|credential)\s*[,)]/i,
333
+ ],
334
+ fix: 'Remove or mask sensitive data before logging',
335
+ },
336
+ {
337
+ id: 'debug-mode-enabled',
338
+ name: 'Debug Mode Enabled in Production',
339
+ description: 'Debug mode can expose sensitive information and stack traces',
340
+ severity: 'low',
341
+ languages: ['javascript', 'typescript', 'python'],
342
+ patterns: [
343
+ /DEBUG\s*=\s*True/,
344
+ /debug\s*:\s*true/,
345
+ /NODE_ENV.*development/,
346
+ /\.enableDebug\s*\(\s*true\s*\)/,
347
+ ],
348
+ fix: 'Disable debug mode in production environments',
349
+ },
350
+ {
351
+ id: 'prototype-pollution',
352
+ name: 'Potential Prototype Pollution',
353
+ description: 'Merging user input into objects can allow prototype pollution attacks',
354
+ severity: 'low',
355
+ languages: ['javascript', 'typescript'],
356
+ patterns: [
357
+ /Object\.assign\s*\(\s*\{\}\s*,[^)]*(?:req\.|body\.|params\.|query\.)/,
358
+ /\{\s*\.\.\.(?:req|body|params|query)/,
359
+ /lodash\.merge\s*\([^)]*(?:req\.|body\.)/,
360
+ /deepmerge\s*\([^)]*(?:req\.|body\.)/,
361
+ ],
362
+ fix: 'Validate and sanitize user input before merging. Use Object.create(null) for dictionaries',
363
+ },
364
+ // ============================================
365
+ // FRAMEWORK-SPECIFIC RULES
366
+ // ============================================
367
+ // --- Next.js ---
368
+ {
369
+ id: 'nextjs-exposed-server-action',
370
+ name: 'Next.js Server Action Without Auth',
371
+ description: 'Server actions are public endpoints and need authentication checks',
372
+ severity: 'high',
373
+ languages: ['javascript', 'typescript'],
374
+ patterns: [
375
+ /['"`]use server['"`]\s*;?\s*(?:export\s+)?(?:async\s+)?function\s+\w+\s*\([^)]*\)\s*\{(?![^}]*(?:auth|session|getServerSession|currentUser))/,
376
+ ],
377
+ fix: 'Add authentication check at the start of server actions using getServerSession() or similar',
378
+ },
379
+ {
380
+ id: 'nextjs-api-route-no-auth',
381
+ name: 'Next.js API Route Without Auth Check',
382
+ description: 'API routes in Next.js are public by default and need explicit auth',
383
+ severity: 'high',
384
+ languages: ['javascript', 'typescript'],
385
+ patterns: [
386
+ /export\s+(?:default\s+)?(?:async\s+)?function\s+(?:GET|POST|PUT|DELETE|PATCH)\s*\([^)]*\)\s*\{(?![^}]{0,500}(?:getServerSession|auth|getToken|verifyToken|currentUser))/,
387
+ ],
388
+ fix: 'Add authentication check using getServerSession() from next-auth or similar',
389
+ },
390
+ {
391
+ id: 'nextjs-dangerouslySetInnerHTML',
392
+ name: 'Next.js dangerouslySetInnerHTML with User Data',
393
+ description: 'Using dangerouslySetInnerHTML with dynamic data can cause XSS',
394
+ severity: 'high',
395
+ languages: ['javascript', 'typescript'],
396
+ patterns: [
397
+ /dangerouslySetInnerHTML\s*=\s*\{\s*\{\s*__html\s*:\s*(?!['"`])/,
398
+ ],
399
+ fix: 'Sanitize HTML using DOMPurify or similar before using dangerouslySetInnerHTML',
400
+ },
401
+ {
402
+ id: 'nextjs-exposed-env',
403
+ name: 'Next.js Private Env Exposed to Client',
404
+ description: 'Environment variables without NEXT_PUBLIC_ prefix should not be in client code',
405
+ severity: 'high',
406
+ languages: ['javascript', 'typescript'],
407
+ patterns: [
408
+ /['"`]use client['"`][\s\S]*process\.env\.(?!NEXT_PUBLIC_)[A-Z_]+/,
409
+ ],
410
+ fix: 'Use NEXT_PUBLIC_ prefix for client-side env vars, or access server env in API routes only',
411
+ },
412
+ // --- Django ---
413
+ {
414
+ id: 'django-debug-true',
415
+ name: 'Django DEBUG=True in Production',
416
+ description: 'Debug mode exposes sensitive information and should never be enabled in production',
417
+ severity: 'critical',
418
+ languages: ['python'],
419
+ patterns: [
420
+ /DEBUG\s*=\s*True/,
421
+ ],
422
+ fix: 'Set DEBUG=False in production and use environment variables',
423
+ },
424
+ {
425
+ id: 'django-secret-key-exposed',
426
+ name: 'Django SECRET_KEY Hardcoded',
427
+ description: 'Hardcoded SECRET_KEY can be extracted and used to forge sessions',
428
+ severity: 'critical',
429
+ languages: ['python'],
430
+ patterns: [
431
+ /SECRET_KEY\s*=\s*['"`][^'"`]{20,}['"`]/,
432
+ ],
433
+ fix: 'Load SECRET_KEY from environment variable: os.environ.get("SECRET_KEY")',
434
+ },
435
+ {
436
+ id: 'django-raw-sql',
437
+ name: 'Django Raw SQL Query',
438
+ description: 'Raw SQL queries with string formatting are vulnerable to SQL injection',
439
+ severity: 'critical',
440
+ languages: ['python'],
441
+ patterns: [
442
+ /\.raw\s*\(\s*f['"`]/,
443
+ /\.raw\s*\(\s*['"`][^'"`]*%s/,
444
+ /\.extra\s*\(\s*where\s*=\s*\[/,
445
+ /cursor\.execute\s*\(\s*f['"`]/,
446
+ ],
447
+ fix: 'Use parameterized queries with %s placeholders and params tuple',
448
+ },
449
+ {
450
+ id: 'django-no-csrf-exempt',
451
+ name: 'Django CSRF Exemption',
452
+ description: 'Disabling CSRF protection exposes the endpoint to cross-site attacks',
453
+ severity: 'high',
454
+ languages: ['python'],
455
+ patterns: [
456
+ /@csrf_exempt/,
457
+ ],
458
+ fix: 'Remove @csrf_exempt and implement proper CSRF handling, or use API tokens for non-browser clients',
459
+ },
460
+ {
461
+ id: 'django-allowed-hosts-all',
462
+ name: 'Django ALLOWED_HOSTS Wildcard',
463
+ description: 'Allowing all hosts can enable host header attacks',
464
+ severity: 'medium',
465
+ languages: ['python'],
466
+ patterns: [
467
+ /ALLOWED_HOSTS\s*=\s*\[\s*['"`]\*['"`]\s*\]/,
468
+ ],
469
+ fix: 'Specify explicit allowed hosts: ALLOWED_HOSTS = ["example.com", "www.example.com"]',
470
+ },
471
+ // --- FastAPI ---
472
+ {
473
+ id: 'fastapi-no-auth-dependency',
474
+ name: 'FastAPI Endpoint Without Auth Dependency',
475
+ description: 'Sensitive endpoints should use Depends() for authentication',
476
+ severity: 'high',
477
+ languages: ['python'],
478
+ patterns: [
479
+ /@app\.(?:post|put|delete|patch)\s*\(\s*['"`]\/(?:admin|user|account|settings)[^'"]*['"`]\s*\)\s*\n(?:async\s+)?def\s+\w+\s*\([^)]*\)(?![^:]*Depends)/,
480
+ ],
481
+ fix: 'Add authentication dependency: async def endpoint(user: User = Depends(get_current_user))',
482
+ },
483
+ {
484
+ id: 'fastapi-cors-all-origins',
485
+ name: 'FastAPI CORS Allow All Origins',
486
+ description: 'Allowing all origins with credentials enabled is a security risk',
487
+ severity: 'medium',
488
+ languages: ['python'],
489
+ patterns: [
490
+ /add_middleware\s*\(\s*CORSMiddleware[^)]*allow_origins\s*=\s*\[\s*['"`]\*['"`]\s*\]/,
491
+ ],
492
+ fix: 'Specify allowed origins explicitly instead of using wildcard',
493
+ },
494
+ // --- NestJS ---
495
+ {
496
+ id: 'nestjs-no-auth-guard',
497
+ name: 'NestJS Controller Without Auth Guard',
498
+ description: 'Controllers handling sensitive data should use authentication guards',
499
+ severity: 'high',
500
+ languages: ['typescript'],
501
+ patterns: [
502
+ /@Controller\s*\(\s*['"`](?:admin|user|account|settings|payment)[^'"]*['"`]\s*\)\s*\nexport\s+class\s+\w+(?![^{]*@UseGuards)/,
503
+ ],
504
+ fix: 'Add @UseGuards(AuthGuard) decorator to the controller or specific routes',
505
+ },
506
+ {
507
+ id: 'nestjs-exposed-internal-exception',
508
+ name: 'NestJS Internal Exception Exposed',
509
+ description: 'Throwing raw errors exposes internal details to clients',
510
+ severity: 'low',
511
+ languages: ['typescript'],
512
+ patterns: [
513
+ /throw\s+new\s+(?:Error|InternalServerErrorException)\s*\(\s*(?:err|error)\.message/,
514
+ ],
515
+ fix: 'Use HttpException with generic message, log details internally',
516
+ },
517
+ // --- React (general) ---
518
+ {
519
+ id: 'react-href-javascript',
520
+ name: 'React href with javascript: Protocol',
521
+ description: 'javascript: URLs in href can execute arbitrary code',
522
+ severity: 'high',
523
+ languages: ['javascript', 'typescript'],
524
+ patterns: [
525
+ /href\s*=\s*\{[^}]*['"`]javascript:/,
526
+ /href\s*=\s*['"`]javascript:/,
527
+ ],
528
+ fix: 'Never use javascript: URLs. Use onClick handlers instead',
529
+ },
530
+ {
531
+ id: 'react-url-state-injection',
532
+ name: 'React URL Parameters in Dangerous Context',
533
+ description: 'URL parameters used in dangerous contexts can cause XSS',
534
+ severity: 'high',
535
+ languages: ['javascript', 'typescript'],
536
+ patterns: [
537
+ /useSearchParams\s*\(\s*\)[\s\S]*dangerouslySetInnerHTML/,
538
+ /searchParams\.get\s*\([^)]+\)[\s\S]*innerHTML/,
539
+ ],
540
+ fix: 'Sanitize URL parameters before using in dangerous contexts',
541
+ },
542
+ // --- Express.js ---
543
+ {
544
+ id: 'express-helmet-missing',
545
+ name: 'Express Missing Security Headers (Helmet)',
546
+ description: 'Express apps should use Helmet for security headers',
547
+ severity: 'medium',
548
+ languages: ['javascript', 'typescript'],
549
+ patterns: [
550
+ /express\s*\(\s*\)(?![^;]*helmet)/,
551
+ ],
552
+ fix: 'Add Helmet middleware: app.use(helmet())',
553
+ },
554
+ {
555
+ id: 'express-body-parser-limit',
556
+ name: 'Express Body Parser Without Size Limit',
557
+ description: 'Unlimited body size can lead to denial of service attacks',
558
+ severity: 'medium',
559
+ languages: ['javascript', 'typescript'],
560
+ patterns: [
561
+ /express\.json\s*\(\s*\)/,
562
+ /bodyParser\.json\s*\(\s*\)/,
563
+ ],
564
+ fix: 'Set a body size limit: express.json({ limit: "10kb" })',
565
+ },
566
+ {
567
+ id: 'express-session-insecure',
568
+ name: 'Express Session Insecure Configuration',
569
+ description: 'Session cookies should be secure and httpOnly',
570
+ severity: 'high',
571
+ languages: ['javascript', 'typescript'],
572
+ patterns: [
573
+ /session\s*\(\s*\{[^}]*secret\s*:[^}]*\}\s*\)(?![^)]*(?:secure|httpOnly))/,
574
+ ],
575
+ fix: 'Configure session with secure options: { cookie: { secure: true, httpOnly: true, sameSite: "strict" } }',
576
+ },
577
+ ];
578
+ function getRuleById(id) {
579
+ return exports.securityRules.find(rule => rule.id === id);
580
+ }
581
+ function getRulesBySeverity(severity) {
582
+ return exports.securityRules.filter(rule => rule.severity === severity);
583
+ }
584
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../../src/scanner/rules/definitions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { SecurityRule } from '../../types';
2
+ export declare function loadRules(licenseKey?: string): Promise<SecurityRule[]>;
3
+ export declare function filterRules(rules: SecurityRule[], options: {
4
+ enabled?: string[];
5
+ disabled?: string[];
6
+ languages?: string[];
7
+ }): SecurityRule[];
8
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/scanner/rules/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,wBAAsB,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA0B5E;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GACA,YAAY,EAAE,CAkBhB"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadRules = loadRules;
4
+ exports.filterRules = filterRules;
5
+ const definitions_1 = require("./definitions");
6
+ const API_BASE_URL = process.env.VIBEGUARD_API_URL || 'https://api.vibeguard.dev';
7
+ async function loadRules(licenseKey) {
8
+ // For now, use local rules
9
+ // In production, this would fetch from the API
10
+ if (process.env.VIBEGUARD_OFFLINE === 'true' || !licenseKey) {
11
+ return definitions_1.securityRules;
12
+ }
13
+ try {
14
+ const response = await fetch(`${API_BASE_URL}/v1/rules`, {
15
+ headers: {
16
+ 'Authorization': `Bearer ${licenseKey}`,
17
+ 'Content-Type': 'application/json',
18
+ },
19
+ });
20
+ if (!response.ok) {
21
+ // Fall back to local rules if API fails
22
+ return definitions_1.securityRules;
23
+ }
24
+ const data = (await response.json());
25
+ return data.rules || definitions_1.securityRules;
26
+ }
27
+ catch {
28
+ // Fall back to local rules on network error
29
+ return definitions_1.securityRules;
30
+ }
31
+ }
32
+ function filterRules(rules, options) {
33
+ let filtered = [...rules];
34
+ if (options.enabled && options.enabled.length > 0) {
35
+ filtered = filtered.filter(rule => options.enabled.includes(rule.id));
36
+ }
37
+ if (options.disabled && options.disabled.length > 0) {
38
+ filtered = filtered.filter(rule => !options.disabled.includes(rule.id));
39
+ }
40
+ if (options.languages && options.languages.length > 0) {
41
+ filtered = filtered.filter(rule => rule.languages.some(lang => options.languages.includes(lang)));
42
+ }
43
+ return filtered;
44
+ }
45
+ //# sourceMappingURL=loader.js.map