devrail 0.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.
@@ -0,0 +1,575 @@
1
+ // src/rules/definitions.ts
2
+ var rules = [
3
+ // ============================================
4
+ // SECRETS
5
+ // ============================================
6
+ {
7
+ id: "secrets.no-plaintext",
8
+ name: "No Plaintext Secrets",
9
+ description: "Detect hardcoded secrets, API keys, passwords in source code",
10
+ category: "secrets",
11
+ severity: "error",
12
+ autofix: false,
13
+ blocking: true,
14
+ scope: "all",
15
+ tool: "gitleaks",
16
+ docs: "https://vibeguard.dev/rules/secrets-no-plaintext",
17
+ rationale: "Hardcoded secrets in source code are a critical security vulnerability. They can be exposed through version control, logs, or error messages.",
18
+ fix: "Move secrets to environment variables or a secrets manager. Use .env files for local development (never commit them).",
19
+ examples: {
20
+ bad: `const API_KEY = "sk-1234567890abcdef";`,
21
+ good: `const API_KEY = process.env.API_KEY;`
22
+ },
23
+ levels: { basic: true, standard: true, strict: true }
24
+ },
25
+ {
26
+ id: "secrets.no-env-commit",
27
+ name: "No .env Files in Git",
28
+ description: "Ensure .env files are not committed to version control",
29
+ category: "secrets",
30
+ severity: "error",
31
+ autofix: true,
32
+ blocking: true,
33
+ scope: "all",
34
+ tool: "builtin",
35
+ docs: "https://vibeguard.dev/rules/secrets-no-env-commit",
36
+ rationale: ".env files often contain sensitive configuration. They should never be committed.",
37
+ fix: "Add .env to .gitignore. Remove any committed .env files from git history.",
38
+ levels: { basic: true, standard: true, strict: true }
39
+ },
40
+ {
41
+ id: "secrets.gitignore-required",
42
+ name: "Gitignore Required",
43
+ description: "Ensure .gitignore exists with common sensitive patterns",
44
+ category: "secrets",
45
+ severity: "warn",
46
+ autofix: true,
47
+ blocking: false,
48
+ scope: "all",
49
+ tool: "builtin",
50
+ docs: "https://vibeguard.dev/rules/secrets-gitignore-required",
51
+ rationale: "A proper .gitignore prevents accidental commits of sensitive files.",
52
+ fix: "Create or update .gitignore with patterns for .env, node_modules, etc.",
53
+ levels: { basic: true, standard: true, strict: true }
54
+ },
55
+ // ============================================
56
+ // DEPENDENCIES
57
+ // ============================================
58
+ {
59
+ id: "deps.lockfile.required",
60
+ name: "Lockfile Required",
61
+ description: "Ensure package-lock.json, yarn.lock, or pnpm-lock.yaml exists",
62
+ category: "deps",
63
+ severity: "error",
64
+ autofix: true,
65
+ blocking: true,
66
+ scope: "all",
67
+ tool: "builtin",
68
+ docs: "https://vibeguard.dev/rules/deps-lockfile-required",
69
+ rationale: "Lockfiles ensure reproducible builds and prevent supply chain attacks through version drift.",
70
+ fix: "Run npm install, yarn install, or pnpm install to generate a lockfile.",
71
+ levels: { basic: true, standard: true, strict: true }
72
+ },
73
+ {
74
+ id: "deps.no-unpinned",
75
+ name: "No Unpinned Dependencies",
76
+ description: "Warn about dependencies using ranges like ^, ~, or *",
77
+ category: "deps",
78
+ severity: "warn",
79
+ autofix: false,
80
+ blocking: false,
81
+ scope: "all",
82
+ tool: "builtin",
83
+ docs: "https://vibeguard.dev/rules/deps-no-unpinned",
84
+ rationale: "Unpinned dependencies can introduce breaking changes or vulnerabilities unexpectedly.",
85
+ fix: "Pin dependencies to exact versions or use a lockfile.",
86
+ levels: { basic: false, standard: true, strict: true }
87
+ },
88
+ {
89
+ id: "deps.no-git-deps",
90
+ name: "No Git Dependencies",
91
+ description: "Disallow dependencies from git URLs",
92
+ category: "deps",
93
+ severity: "warn",
94
+ autofix: false,
95
+ blocking: false,
96
+ scope: "all",
97
+ tool: "builtin",
98
+ docs: "https://vibeguard.dev/rules/deps-no-git-deps",
99
+ rationale: "Git dependencies bypass npm registry security checks and can change without version bumps.",
100
+ fix: "Publish the dependency to npm or use a private registry.",
101
+ levels: { basic: false, standard: true, strict: true }
102
+ },
103
+ {
104
+ id: "deps.no-vulnerable",
105
+ name: "No Vulnerable Dependencies",
106
+ description: "Scan dependencies for known vulnerabilities",
107
+ category: "deps",
108
+ severity: "error",
109
+ autofix: false,
110
+ blocking: true,
111
+ scope: "all",
112
+ tool: "osv-scanner",
113
+ docs: "https://vibeguard.dev/rules/deps-no-vulnerable",
114
+ rationale: "Known vulnerabilities in dependencies are a common attack vector.",
115
+ fix: "Update vulnerable dependencies or find alternatives.",
116
+ levels: { basic: true, standard: true, strict: true }
117
+ },
118
+ {
119
+ id: "deps.no-typosquatting",
120
+ name: "No Typosquatting Packages",
121
+ description: "Detect potentially malicious packages with names similar to popular ones",
122
+ category: "deps",
123
+ severity: "error",
124
+ autofix: false,
125
+ blocking: true,
126
+ scope: "all",
127
+ tool: "builtin",
128
+ docs: "https://vibeguard.dev/rules/deps-no-typosquatting",
129
+ rationale: "Typosquatting is a supply chain attack where malicious packages mimic popular package names.",
130
+ fix: "Verify package names carefully. Use official package names.",
131
+ levels: { basic: true, standard: true, strict: true }
132
+ },
133
+ {
134
+ id: "deps.license-check",
135
+ name: "License Compatibility Check",
136
+ description: "Ensure dependencies have compatible licenses",
137
+ category: "deps",
138
+ severity: "warn",
139
+ autofix: false,
140
+ blocking: false,
141
+ scope: "all",
142
+ tool: "builtin",
143
+ docs: "https://vibeguard.dev/rules/deps-license-check",
144
+ rationale: "Incompatible licenses can create legal issues for your project.",
145
+ fix: "Review and replace dependencies with incompatible licenses.",
146
+ levels: { basic: false, standard: false, strict: true }
147
+ },
148
+ // ============================================
149
+ // SECURITY
150
+ // ============================================
151
+ {
152
+ id: "security.headers.required",
153
+ name: "Security Headers Required",
154
+ description: "Ensure security headers are configured (CSP, HSTS, etc.)",
155
+ category: "security",
156
+ severity: "warn",
157
+ autofix: false,
158
+ blocking: false,
159
+ scope: "all",
160
+ tool: "semgrep",
161
+ docs: "https://vibeguard.dev/rules/security-headers-required",
162
+ rationale: "Security headers protect against XSS, clickjacking, and other browser-based attacks.",
163
+ fix: "Add helmet middleware (Express) or configure headers in next.config.js.",
164
+ examples: {
165
+ good: `import helmet from 'helmet';
166
+ app.use(helmet());`
167
+ },
168
+ levels: { basic: false, standard: true, strict: true }
169
+ },
170
+ {
171
+ id: "security.cors.safe-default",
172
+ name: "Safe CORS Configuration",
173
+ description: "Detect overly permissive CORS configurations",
174
+ category: "security",
175
+ severity: "error",
176
+ autofix: false,
177
+ blocking: true,
178
+ scope: "all",
179
+ tool: "semgrep",
180
+ docs: "https://vibeguard.dev/rules/security-cors-safe-default",
181
+ rationale: "Permissive CORS (origin: *) can expose your API to cross-origin attacks.",
182
+ fix: "Restrict CORS to specific trusted origins.",
183
+ examples: {
184
+ bad: `cors({ origin: '*' })`,
185
+ good: `cors({ origin: ['https://myapp.com'] })`
186
+ },
187
+ levels: { basic: true, standard: true, strict: true }
188
+ },
189
+ {
190
+ id: "security.no-eval",
191
+ name: "No eval() or Function()",
192
+ description: "Disallow eval, Function constructor, and similar dynamic code execution",
193
+ category: "security",
194
+ severity: "error",
195
+ autofix: false,
196
+ blocking: true,
197
+ scope: "all",
198
+ tool: "eslint",
199
+ docs: "https://vibeguard.dev/rules/security-no-eval",
200
+ rationale: "Dynamic code execution is a major injection vulnerability vector.",
201
+ fix: "Use safer alternatives like JSON.parse for data, or refactor logic.",
202
+ levels: { basic: true, standard: true, strict: true }
203
+ },
204
+ {
205
+ id: "security.no-unsafe-regex",
206
+ name: "No Unsafe Regular Expressions",
207
+ description: "Detect regex patterns vulnerable to ReDoS attacks",
208
+ category: "security",
209
+ severity: "warn",
210
+ autofix: false,
211
+ blocking: false,
212
+ scope: "all",
213
+ tool: "eslint",
214
+ docs: "https://vibeguard.dev/rules/security-no-unsafe-regex",
215
+ rationale: "Catastrophic backtracking in regex can cause denial of service.",
216
+ fix: "Simplify regex patterns or use a safe regex library.",
217
+ levels: { basic: false, standard: true, strict: true }
218
+ },
219
+ {
220
+ id: "security.no-prototype-pollution",
221
+ name: "No Prototype Pollution",
222
+ description: "Detect patterns that could lead to prototype pollution",
223
+ category: "security",
224
+ severity: "error",
225
+ autofix: false,
226
+ blocking: true,
227
+ scope: "all",
228
+ tool: "semgrep",
229
+ docs: "https://vibeguard.dev/rules/security-no-prototype-pollution",
230
+ rationale: "Prototype pollution can lead to property injection and RCE.",
231
+ fix: "Use Object.create(null) for dictionaries, validate object keys.",
232
+ levels: { basic: true, standard: true, strict: true }
233
+ },
234
+ // ============================================
235
+ // AUTH
236
+ // ============================================
237
+ {
238
+ id: "auth.no-weak-jwt",
239
+ name: "No Weak JWT Configuration",
240
+ description: "Detect weak JWT algorithms (none, HS256 with weak secrets)",
241
+ category: "auth",
242
+ severity: "error",
243
+ autofix: false,
244
+ blocking: true,
245
+ scope: "all",
246
+ tool: "semgrep",
247
+ docs: "https://vibeguard.dev/rules/auth-no-weak-jwt",
248
+ rationale: "Weak JWT configuration allows token forgery and authentication bypass.",
249
+ fix: 'Use RS256 or ES256 algorithms. Never use "none". Use strong secrets.',
250
+ examples: {
251
+ bad: `jwt.sign(payload, 'secret', { algorithm: 'none' })`,
252
+ good: `jwt.sign(payload, privateKey, { algorithm: 'RS256' })`
253
+ },
254
+ levels: { basic: true, standard: true, strict: true }
255
+ },
256
+ {
257
+ id: "auth.no-hardcoded-credentials",
258
+ name: "No Hardcoded Credentials",
259
+ description: "Detect hardcoded usernames, passwords, or tokens in auth logic",
260
+ category: "auth",
261
+ severity: "error",
262
+ autofix: false,
263
+ blocking: true,
264
+ scope: "all",
265
+ tool: "semgrep",
266
+ docs: "https://vibeguard.dev/rules/auth-no-hardcoded-credentials",
267
+ rationale: "Hardcoded credentials are easily discovered and exploited.",
268
+ fix: "Use environment variables or a secrets manager.",
269
+ levels: { basic: true, standard: true, strict: true }
270
+ },
271
+ {
272
+ id: "auth.session-secure",
273
+ name: "Secure Session Configuration",
274
+ description: "Ensure session cookies have secure, httpOnly, sameSite flags",
275
+ category: "auth",
276
+ severity: "warn",
277
+ autofix: false,
278
+ blocking: false,
279
+ scope: "all",
280
+ tool: "semgrep",
281
+ docs: "https://vibeguard.dev/rules/auth-session-secure",
282
+ rationale: "Insecure session cookies can be stolen via XSS or MITM attacks.",
283
+ fix: 'Set secure: true, httpOnly: true, sameSite: "strict" on session cookies.',
284
+ levels: { basic: false, standard: true, strict: true }
285
+ },
286
+ // ============================================
287
+ // API
288
+ // ============================================
289
+ {
290
+ id: "api.validation.required",
291
+ name: "Input Validation Required",
292
+ description: "Ensure API endpoints validate input with a schema library",
293
+ category: "api",
294
+ severity: "warn",
295
+ autofix: false,
296
+ blocking: false,
297
+ scope: "all",
298
+ tool: "semgrep",
299
+ docs: "https://vibeguard.dev/rules/api-validation-required",
300
+ rationale: "Unvalidated input is the root cause of most injection vulnerabilities.",
301
+ fix: "Use zod, joi, yup, or similar for input validation.",
302
+ examples: {
303
+ bad: `app.post('/user', (req, res) => { db.insert(req.body); });`,
304
+ good: `app.post('/user', (req, res) => { const data = userSchema.parse(req.body); });`
305
+ },
306
+ levels: { basic: false, standard: true, strict: true }
307
+ },
308
+ {
309
+ id: "api.rate-limiting",
310
+ name: "Rate Limiting Required",
311
+ description: "Ensure rate limiting is configured on API endpoints",
312
+ category: "api",
313
+ severity: "warn",
314
+ autofix: false,
315
+ blocking: false,
316
+ scope: "all",
317
+ tool: "semgrep",
318
+ docs: "https://vibeguard.dev/rules/api-rate-limiting",
319
+ rationale: "Without rate limiting, APIs are vulnerable to brute force and DoS attacks.",
320
+ fix: "Add express-rate-limit or similar middleware.",
321
+ levels: { basic: false, standard: false, strict: true }
322
+ },
323
+ {
324
+ id: "api.no-sensitive-logging",
325
+ name: "No Sensitive Data in Logs",
326
+ description: "Detect logging of passwords, tokens, or PII",
327
+ category: "api",
328
+ severity: "error",
329
+ autofix: false,
330
+ blocking: true,
331
+ scope: "all",
332
+ tool: "semgrep",
333
+ docs: "https://vibeguard.dev/rules/api-no-sensitive-logging",
334
+ rationale: "Sensitive data in logs can be exposed through log aggregation systems.",
335
+ fix: "Redact sensitive fields before logging. Use structured logging.",
336
+ levels: { basic: true, standard: true, strict: true }
337
+ },
338
+ // ============================================
339
+ // SQL
340
+ // ============================================
341
+ {
342
+ id: "sql.no-string-concat",
343
+ name: "No SQL String Concatenation",
344
+ description: "Detect SQL queries built with string concatenation",
345
+ category: "sql",
346
+ severity: "error",
347
+ autofix: false,
348
+ blocking: true,
349
+ scope: "all",
350
+ tool: "semgrep",
351
+ docs: "https://vibeguard.dev/rules/sql-no-string-concat",
352
+ rationale: "String concatenation in SQL queries leads to SQL injection.",
353
+ fix: "Use parameterized queries or an ORM.",
354
+ examples: {
355
+ bad: `db.query("SELECT * FROM users WHERE id = " + userId)`,
356
+ good: `db.query("SELECT * FROM users WHERE id = $1", [userId])`
357
+ },
358
+ levels: { basic: true, standard: true, strict: true }
359
+ },
360
+ {
361
+ id: "sql.no-raw-queries",
362
+ name: "Prefer ORM Over Raw Queries",
363
+ description: "Warn when using raw SQL queries instead of ORM methods",
364
+ category: "sql",
365
+ severity: "info",
366
+ autofix: false,
367
+ blocking: false,
368
+ scope: "all",
369
+ tool: "semgrep",
370
+ docs: "https://vibeguard.dev/rules/sql-no-raw-queries",
371
+ rationale: "ORMs provide built-in protection against SQL injection.",
372
+ fix: "Use Prisma, Drizzle, or TypeORM query builders.",
373
+ levels: { basic: false, standard: false, strict: true }
374
+ },
375
+ // ============================================
376
+ // TESTS
377
+ // ============================================
378
+ {
379
+ id: "tests.unit.required",
380
+ name: "Unit Tests Required",
381
+ description: "Ensure test files exist for the project",
382
+ category: "tests",
383
+ severity: "warn",
384
+ autofix: false,
385
+ blocking: false,
386
+ scope: "all",
387
+ tool: "builtin",
388
+ docs: "https://vibeguard.dev/rules/tests-unit-required",
389
+ rationale: "Tests catch regressions and document expected behavior.",
390
+ fix: "Create test files using Jest, Vitest, or your preferred test runner.",
391
+ levels: { basic: false, standard: true, strict: true }
392
+ },
393
+ {
394
+ id: "tests.coverage.min-50",
395
+ name: "Minimum 50% Test Coverage",
396
+ description: "Ensure at least 50% code coverage",
397
+ category: "tests",
398
+ severity: "warn",
399
+ autofix: false,
400
+ blocking: false,
401
+ scope: "all",
402
+ tool: "vitest",
403
+ docs: "https://vibeguard.dev/rules/tests-coverage-min-50",
404
+ rationale: "Minimum coverage ensures critical paths are tested.",
405
+ fix: "Add tests for uncovered code paths.",
406
+ levels: { basic: false, standard: true, strict: false }
407
+ },
408
+ {
409
+ id: "tests.coverage.min-80",
410
+ name: "Minimum 80% Test Coverage",
411
+ description: "Ensure at least 80% code coverage",
412
+ category: "tests",
413
+ severity: "error",
414
+ autofix: false,
415
+ blocking: true,
416
+ scope: "all",
417
+ tool: "vitest",
418
+ docs: "https://vibeguard.dev/rules/tests-coverage-min-80",
419
+ rationale: "High coverage reduces the risk of regressions.",
420
+ fix: "Add tests for uncovered code paths.",
421
+ levels: { basic: false, standard: false, strict: true }
422
+ },
423
+ {
424
+ id: "tests.no-skipped",
425
+ name: "No Skipped Tests",
426
+ description: "Detect .skip() or .only() left in test files",
427
+ category: "tests",
428
+ severity: "warn",
429
+ autofix: false,
430
+ blocking: false,
431
+ scope: "all",
432
+ tool: "eslint",
433
+ docs: "https://vibeguard.dev/rules/tests-no-skipped",
434
+ rationale: "Skipped tests can hide failures. .only() can exclude other tests.",
435
+ fix: "Remove .skip() and .only() before committing.",
436
+ levels: { basic: true, standard: true, strict: true }
437
+ },
438
+ // ============================================
439
+ // LOGGING
440
+ // ============================================
441
+ {
442
+ id: "logging.no-pii",
443
+ name: "No PII in Logs",
444
+ description: "Detect logging of personally identifiable information",
445
+ category: "logging",
446
+ severity: "error",
447
+ autofix: false,
448
+ blocking: true,
449
+ scope: "all",
450
+ tool: "semgrep",
451
+ docs: "https://vibeguard.dev/rules/logging-no-pii",
452
+ rationale: "PII in logs violates privacy regulations (GDPR, CCPA).",
453
+ fix: "Redact or hash PII before logging.",
454
+ levels: { basic: false, standard: true, strict: true }
455
+ },
456
+ {
457
+ id: "logging.no-console",
458
+ name: "No console.log in Production",
459
+ description: "Detect console.log statements that should use a logger",
460
+ category: "logging",
461
+ severity: "warn",
462
+ autofix: false,
463
+ blocking: false,
464
+ scope: "all",
465
+ tool: "eslint",
466
+ docs: "https://vibeguard.dev/rules/logging-no-console",
467
+ rationale: "console.log lacks log levels, formatting, and can leak sensitive data.",
468
+ fix: "Use a structured logger like pino or winston.",
469
+ levels: { basic: false, standard: true, strict: true }
470
+ },
471
+ // ============================================
472
+ // CODE QUALITY
473
+ // ============================================
474
+ {
475
+ id: "code.no-any",
476
+ name: "No TypeScript any",
477
+ description: "Disallow the any type in TypeScript",
478
+ category: "code",
479
+ severity: "warn",
480
+ autofix: false,
481
+ blocking: false,
482
+ scope: "all",
483
+ tool: "eslint",
484
+ docs: "https://vibeguard.dev/rules/code-no-any",
485
+ rationale: "any disables type checking and can hide bugs.",
486
+ fix: "Use proper types, unknown, or generics instead.",
487
+ levels: { basic: false, standard: true, strict: true }
488
+ },
489
+ {
490
+ id: "code.strict-mode",
491
+ name: "TypeScript Strict Mode",
492
+ description: "Ensure TypeScript strict mode is enabled",
493
+ category: "code",
494
+ severity: "warn",
495
+ autofix: true,
496
+ blocking: false,
497
+ scope: "all",
498
+ tool: "builtin",
499
+ docs: "https://vibeguard.dev/rules/code-strict-mode",
500
+ rationale: "Strict mode catches more errors at compile time.",
501
+ fix: 'Add "strict": true to tsconfig.json.',
502
+ levels: { basic: false, standard: true, strict: true }
503
+ },
504
+ {
505
+ id: "code.no-unused-vars",
506
+ name: "No Unused Variables",
507
+ description: "Detect unused variables and imports",
508
+ category: "code",
509
+ severity: "warn",
510
+ autofix: true,
511
+ blocking: false,
512
+ scope: "all",
513
+ tool: "eslint",
514
+ docs: "https://vibeguard.dev/rules/code-no-unused-vars",
515
+ rationale: "Unused code is dead weight and can indicate bugs.",
516
+ fix: "Remove unused variables or prefix with underscore.",
517
+ levels: { basic: true, standard: true, strict: true }
518
+ },
519
+ // ============================================
520
+ // CONFIG
521
+ // ============================================
522
+ {
523
+ id: "config.node-version",
524
+ name: "Node Version Specified",
525
+ description: "Ensure Node.js version is specified in package.json or .nvmrc",
526
+ category: "config",
527
+ severity: "info",
528
+ autofix: true,
529
+ blocking: false,
530
+ scope: "all",
531
+ tool: "builtin",
532
+ docs: "https://vibeguard.dev/rules/config-node-version",
533
+ rationale: "Specifying Node version ensures consistent environments.",
534
+ fix: "Add engines.node to package.json or create .nvmrc.",
535
+ levels: { basic: false, standard: true, strict: true }
536
+ },
537
+ {
538
+ id: "config.editor-config",
539
+ name: "EditorConfig Present",
540
+ description: "Ensure .editorconfig exists for consistent formatting",
541
+ category: "config",
542
+ severity: "info",
543
+ autofix: true,
544
+ blocking: false,
545
+ scope: "all",
546
+ tool: "builtin",
547
+ docs: "https://vibeguard.dev/rules/config-editor-config",
548
+ rationale: "EditorConfig ensures consistent formatting across editors.",
549
+ fix: "Create .editorconfig with project standards.",
550
+ levels: { basic: false, standard: true, strict: true }
551
+ }
552
+ ];
553
+ var ruleMap = new Map(rules.map((r) => [r.id, r]));
554
+ function getRuleById(id) {
555
+ return ruleMap.get(id);
556
+ }
557
+ function getRulesByCategory(category) {
558
+ return rules.filter((r) => r.category === category);
559
+ }
560
+ function getRulesByLevel(level) {
561
+ return rules.filter((r) => r.levels[level]);
562
+ }
563
+ function getRulesByTool(tool) {
564
+ return rules.filter((r) => r.tool === tool);
565
+ }
566
+
567
+ export {
568
+ rules,
569
+ ruleMap,
570
+ getRuleById,
571
+ getRulesByCategory,
572
+ getRulesByLevel,
573
+ getRulesByTool
574
+ };
575
+ //# sourceMappingURL=chunk-J22FFU7Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rules/definitions.ts"],"sourcesContent":["import type { RuleDefinition } from '../types/index.js';\n\nexport const rules: RuleDefinition[] = [\n // ============================================\n // SECRETS\n // ============================================\n {\n id: 'secrets.no-plaintext',\n name: 'No Plaintext Secrets',\n description: 'Detect hardcoded secrets, API keys, passwords in source code',\n category: 'secrets',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'gitleaks',\n docs: 'https://vibeguard.dev/rules/secrets-no-plaintext',\n rationale:\n 'Hardcoded secrets in source code are a critical security vulnerability. They can be exposed through version control, logs, or error messages.',\n fix: 'Move secrets to environment variables or a secrets manager. Use .env files for local development (never commit them).',\n examples: {\n bad: `const API_KEY = \"sk-1234567890abcdef\";`,\n good: `const API_KEY = process.env.API_KEY;`,\n },\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'secrets.no-env-commit',\n name: 'No .env Files in Git',\n description: 'Ensure .env files are not committed to version control',\n category: 'secrets',\n severity: 'error',\n autofix: true,\n blocking: true,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/secrets-no-env-commit',\n rationale:\n '.env files often contain sensitive configuration. They should never be committed.',\n fix: 'Add .env to .gitignore. Remove any committed .env files from git history.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'secrets.gitignore-required',\n name: 'Gitignore Required',\n description: 'Ensure .gitignore exists with common sensitive patterns',\n category: 'secrets',\n severity: 'warn',\n autofix: true,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/secrets-gitignore-required',\n rationale: 'A proper .gitignore prevents accidental commits of sensitive files.',\n fix: 'Create or update .gitignore with patterns for .env, node_modules, etc.',\n levels: { basic: true, standard: true, strict: true },\n },\n\n // ============================================\n // DEPENDENCIES\n // ============================================\n {\n id: 'deps.lockfile.required',\n name: 'Lockfile Required',\n description: 'Ensure package-lock.json, yarn.lock, or pnpm-lock.yaml exists',\n category: 'deps',\n severity: 'error',\n autofix: true,\n blocking: true,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/deps-lockfile-required',\n rationale:\n 'Lockfiles ensure reproducible builds and prevent supply chain attacks through version drift.',\n fix: 'Run npm install, yarn install, or pnpm install to generate a lockfile.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'deps.no-unpinned',\n name: 'No Unpinned Dependencies',\n description: 'Warn about dependencies using ranges like ^, ~, or *',\n category: 'deps',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/deps-no-unpinned',\n rationale:\n 'Unpinned dependencies can introduce breaking changes or vulnerabilities unexpectedly.',\n fix: 'Pin dependencies to exact versions or use a lockfile.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'deps.no-git-deps',\n name: 'No Git Dependencies',\n description: 'Disallow dependencies from git URLs',\n category: 'deps',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/deps-no-git-deps',\n rationale:\n 'Git dependencies bypass npm registry security checks and can change without version bumps.',\n fix: 'Publish the dependency to npm or use a private registry.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'deps.no-vulnerable',\n name: 'No Vulnerable Dependencies',\n description: 'Scan dependencies for known vulnerabilities',\n category: 'deps',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'osv-scanner',\n docs: 'https://vibeguard.dev/rules/deps-no-vulnerable',\n rationale: 'Known vulnerabilities in dependencies are a common attack vector.',\n fix: 'Update vulnerable dependencies or find alternatives.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'deps.no-typosquatting',\n name: 'No Typosquatting Packages',\n description: 'Detect potentially malicious packages with names similar to popular ones',\n category: 'deps',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/deps-no-typosquatting',\n rationale:\n 'Typosquatting is a supply chain attack where malicious packages mimic popular package names.',\n fix: 'Verify package names carefully. Use official package names.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'deps.license-check',\n name: 'License Compatibility Check',\n description: 'Ensure dependencies have compatible licenses',\n category: 'deps',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/deps-license-check',\n rationale: 'Incompatible licenses can create legal issues for your project.',\n fix: 'Review and replace dependencies with incompatible licenses.',\n levels: { basic: false, standard: false, strict: true },\n },\n\n // ============================================\n // SECURITY\n // ============================================\n {\n id: 'security.headers.required',\n name: 'Security Headers Required',\n description: 'Ensure security headers are configured (CSP, HSTS, etc.)',\n category: 'security',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/security-headers-required',\n rationale:\n 'Security headers protect against XSS, clickjacking, and other browser-based attacks.',\n fix: 'Add helmet middleware (Express) or configure headers in next.config.js.',\n examples: {\n good: `import helmet from 'helmet';\\napp.use(helmet());`,\n },\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'security.cors.safe-default',\n name: 'Safe CORS Configuration',\n description: 'Detect overly permissive CORS configurations',\n category: 'security',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/security-cors-safe-default',\n rationale: 'Permissive CORS (origin: *) can expose your API to cross-origin attacks.',\n fix: 'Restrict CORS to specific trusted origins.',\n examples: {\n bad: `cors({ origin: '*' })`,\n good: `cors({ origin: ['https://myapp.com'] })`,\n },\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'security.no-eval',\n name: 'No eval() or Function()',\n description: 'Disallow eval, Function constructor, and similar dynamic code execution',\n category: 'security',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/security-no-eval',\n rationale: 'Dynamic code execution is a major injection vulnerability vector.',\n fix: 'Use safer alternatives like JSON.parse for data, or refactor logic.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'security.no-unsafe-regex',\n name: 'No Unsafe Regular Expressions',\n description: 'Detect regex patterns vulnerable to ReDoS attacks',\n category: 'security',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/security-no-unsafe-regex',\n rationale: 'Catastrophic backtracking in regex can cause denial of service.',\n fix: 'Simplify regex patterns or use a safe regex library.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'security.no-prototype-pollution',\n name: 'No Prototype Pollution',\n description: 'Detect patterns that could lead to prototype pollution',\n category: 'security',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/security-no-prototype-pollution',\n rationale: 'Prototype pollution can lead to property injection and RCE.',\n fix: 'Use Object.create(null) for dictionaries, validate object keys.',\n levels: { basic: true, standard: true, strict: true },\n },\n\n // ============================================\n // AUTH\n // ============================================\n {\n id: 'auth.no-weak-jwt',\n name: 'No Weak JWT Configuration',\n description: 'Detect weak JWT algorithms (none, HS256 with weak secrets)',\n category: 'auth',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/auth-no-weak-jwt',\n rationale: 'Weak JWT configuration allows token forgery and authentication bypass.',\n fix: 'Use RS256 or ES256 algorithms. Never use \"none\". Use strong secrets.',\n examples: {\n bad: `jwt.sign(payload, 'secret', { algorithm: 'none' })`,\n good: `jwt.sign(payload, privateKey, { algorithm: 'RS256' })`,\n },\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'auth.no-hardcoded-credentials',\n name: 'No Hardcoded Credentials',\n description: 'Detect hardcoded usernames, passwords, or tokens in auth logic',\n category: 'auth',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/auth-no-hardcoded-credentials',\n rationale: 'Hardcoded credentials are easily discovered and exploited.',\n fix: 'Use environment variables or a secrets manager.',\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'auth.session-secure',\n name: 'Secure Session Configuration',\n description: 'Ensure session cookies have secure, httpOnly, sameSite flags',\n category: 'auth',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/auth-session-secure',\n rationale: 'Insecure session cookies can be stolen via XSS or MITM attacks.',\n fix: 'Set secure: true, httpOnly: true, sameSite: \"strict\" on session cookies.',\n levels: { basic: false, standard: true, strict: true },\n },\n\n // ============================================\n // API\n // ============================================\n {\n id: 'api.validation.required',\n name: 'Input Validation Required',\n description: 'Ensure API endpoints validate input with a schema library',\n category: 'api',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/api-validation-required',\n rationale: 'Unvalidated input is the root cause of most injection vulnerabilities.',\n fix: 'Use zod, joi, yup, or similar for input validation.',\n examples: {\n bad: `app.post('/user', (req, res) => { db.insert(req.body); });`,\n good: `app.post('/user', (req, res) => { const data = userSchema.parse(req.body); });`,\n },\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'api.rate-limiting',\n name: 'Rate Limiting Required',\n description: 'Ensure rate limiting is configured on API endpoints',\n category: 'api',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/api-rate-limiting',\n rationale: 'Without rate limiting, APIs are vulnerable to brute force and DoS attacks.',\n fix: 'Add express-rate-limit or similar middleware.',\n levels: { basic: false, standard: false, strict: true },\n },\n {\n id: 'api.no-sensitive-logging',\n name: 'No Sensitive Data in Logs',\n description: 'Detect logging of passwords, tokens, or PII',\n category: 'api',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/api-no-sensitive-logging',\n rationale: 'Sensitive data in logs can be exposed through log aggregation systems.',\n fix: 'Redact sensitive fields before logging. Use structured logging.',\n levels: { basic: true, standard: true, strict: true },\n },\n\n // ============================================\n // SQL\n // ============================================\n {\n id: 'sql.no-string-concat',\n name: 'No SQL String Concatenation',\n description: 'Detect SQL queries built with string concatenation',\n category: 'sql',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/sql-no-string-concat',\n rationale: 'String concatenation in SQL queries leads to SQL injection.',\n fix: 'Use parameterized queries or an ORM.',\n examples: {\n bad: `db.query(\"SELECT * FROM users WHERE id = \" + userId)`,\n good: `db.query(\"SELECT * FROM users WHERE id = $1\", [userId])`,\n },\n levels: { basic: true, standard: true, strict: true },\n },\n {\n id: 'sql.no-raw-queries',\n name: 'Prefer ORM Over Raw Queries',\n description: 'Warn when using raw SQL queries instead of ORM methods',\n category: 'sql',\n severity: 'info',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/sql-no-raw-queries',\n rationale: 'ORMs provide built-in protection against SQL injection.',\n fix: 'Use Prisma, Drizzle, or TypeORM query builders.',\n levels: { basic: false, standard: false, strict: true },\n },\n\n // ============================================\n // TESTS\n // ============================================\n {\n id: 'tests.unit.required',\n name: 'Unit Tests Required',\n description: 'Ensure test files exist for the project',\n category: 'tests',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/tests-unit-required',\n rationale: 'Tests catch regressions and document expected behavior.',\n fix: 'Create test files using Jest, Vitest, or your preferred test runner.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'tests.coverage.min-50',\n name: 'Minimum 50% Test Coverage',\n description: 'Ensure at least 50% code coverage',\n category: 'tests',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'vitest',\n docs: 'https://vibeguard.dev/rules/tests-coverage-min-50',\n rationale: 'Minimum coverage ensures critical paths are tested.',\n fix: 'Add tests for uncovered code paths.',\n levels: { basic: false, standard: true, strict: false },\n },\n {\n id: 'tests.coverage.min-80',\n name: 'Minimum 80% Test Coverage',\n description: 'Ensure at least 80% code coverage',\n category: 'tests',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'vitest',\n docs: 'https://vibeguard.dev/rules/tests-coverage-min-80',\n rationale: 'High coverage reduces the risk of regressions.',\n fix: 'Add tests for uncovered code paths.',\n levels: { basic: false, standard: false, strict: true },\n },\n {\n id: 'tests.no-skipped',\n name: 'No Skipped Tests',\n description: 'Detect .skip() or .only() left in test files',\n category: 'tests',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/tests-no-skipped',\n rationale: 'Skipped tests can hide failures. .only() can exclude other tests.',\n fix: 'Remove .skip() and .only() before committing.',\n levels: { basic: true, standard: true, strict: true },\n },\n\n // ============================================\n // LOGGING\n // ============================================\n {\n id: 'logging.no-pii',\n name: 'No PII in Logs',\n description: 'Detect logging of personally identifiable information',\n category: 'logging',\n severity: 'error',\n autofix: false,\n blocking: true,\n scope: 'all',\n tool: 'semgrep',\n docs: 'https://vibeguard.dev/rules/logging-no-pii',\n rationale: 'PII in logs violates privacy regulations (GDPR, CCPA).',\n fix: 'Redact or hash PII before logging.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'logging.no-console',\n name: 'No console.log in Production',\n description: 'Detect console.log statements that should use a logger',\n category: 'logging',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/logging-no-console',\n rationale: 'console.log lacks log levels, formatting, and can leak sensitive data.',\n fix: 'Use a structured logger like pino or winston.',\n levels: { basic: false, standard: true, strict: true },\n },\n\n // ============================================\n // CODE QUALITY\n // ============================================\n {\n id: 'code.no-any',\n name: 'No TypeScript any',\n description: 'Disallow the any type in TypeScript',\n category: 'code',\n severity: 'warn',\n autofix: false,\n blocking: false,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/code-no-any',\n rationale: 'any disables type checking and can hide bugs.',\n fix: 'Use proper types, unknown, or generics instead.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'code.strict-mode',\n name: 'TypeScript Strict Mode',\n description: 'Ensure TypeScript strict mode is enabled',\n category: 'code',\n severity: 'warn',\n autofix: true,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/code-strict-mode',\n rationale: 'Strict mode catches more errors at compile time.',\n fix: 'Add \"strict\": true to tsconfig.json.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'code.no-unused-vars',\n name: 'No Unused Variables',\n description: 'Detect unused variables and imports',\n category: 'code',\n severity: 'warn',\n autofix: true,\n blocking: false,\n scope: 'all',\n tool: 'eslint',\n docs: 'https://vibeguard.dev/rules/code-no-unused-vars',\n rationale: 'Unused code is dead weight and can indicate bugs.',\n fix: 'Remove unused variables or prefix with underscore.',\n levels: { basic: true, standard: true, strict: true },\n },\n\n // ============================================\n // CONFIG\n // ============================================\n {\n id: 'config.node-version',\n name: 'Node Version Specified',\n description: 'Ensure Node.js version is specified in package.json or .nvmrc',\n category: 'config',\n severity: 'info',\n autofix: true,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/config-node-version',\n rationale: 'Specifying Node version ensures consistent environments.',\n fix: 'Add engines.node to package.json or create .nvmrc.',\n levels: { basic: false, standard: true, strict: true },\n },\n {\n id: 'config.editor-config',\n name: 'EditorConfig Present',\n description: 'Ensure .editorconfig exists for consistent formatting',\n category: 'config',\n severity: 'info',\n autofix: true,\n blocking: false,\n scope: 'all',\n tool: 'builtin',\n docs: 'https://vibeguard.dev/rules/config-editor-config',\n rationale: 'EditorConfig ensures consistent formatting across editors.',\n fix: 'Create .editorconfig with project standards.',\n levels: { basic: false, standard: true, strict: true },\n },\n];\n\nexport const ruleMap = new Map<string, RuleDefinition>(rules.map((r) => [r.id, r]));\n\nexport function getRuleById(id: string): RuleDefinition | undefined {\n return ruleMap.get(id);\n}\n\nexport function getRulesByCategory(category: string): RuleDefinition[] {\n return rules.filter((r) => r.category === category);\n}\n\nexport function getRulesByLevel(level: 'basic' | 'standard' | 'strict'): RuleDefinition[] {\n return rules.filter((r) => r.levels[level]);\n}\n\nexport function getRulesByTool(tool: string): RuleDefinition[] {\n return rules.filter((r) => r.tool === tool);\n}\n"],"mappings":"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","names":[]}