@quantracode/vibecheck 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,31 +1,34 @@
1
1
  # @quantracode/vibecheck
2
2
 
3
- A deterministic, local-only security scanner for modern web applications. Designed to catch common security issues in Next.js, Express, and other Node.js projects with high precision and low false positives.
3
+ The first AI Enforcement Security tool. Proves whether AI-written code actually enforces the security it claims not just implied, commented, or assumed.
4
4
 
5
- ## Quickstart (No Install)
5
+ ## What is AI Enforcement Security?
6
6
 
7
- Run VibeCheck instantly without installation:
7
+ Traditional security tools scan for vulnerabilities. VibeCheck verifies enforcement reality. That's a fundamentally different job.
8
8
 
9
- ```bash
10
- # Using npx
11
- npx @quantracode/vibecheck scan --fail-on off --out vibecheck-scan.json
9
+ AI-generated code often hallucinates security guarantees. It writes comments claiming protection exists, imports security libraries but doesn't use them, or creates middleware that never gets wired up. VibeCheck detects these patterns and proves what's actually enforced.
12
10
 
13
- # Using pnpm dlx
14
- pnpm dlx @quantracode/vibecheck scan --fail-on off --out vibecheck-scan.json
15
- ```
11
+ **Key Principles:**
12
+ - **Deterministic** No LLM calls, results are reproducible
13
+ - **Local-only** — All analysis runs on your machine, code never uploaded
14
+ - **Low false positives** — Precision over recall
15
+ - **Framework-aware** — Built for Next.js, Express patterns
16
+ - **Enforcement-focused** — Proves what's enforced, not just scanned
16
17
 
17
- ### Scan Another Folder
18
+ ## Quick Start
18
19
 
19
20
  ```bash
20
- npx @quantracode/vibecheck scan --target ../my-other-app --out scan.json
21
+ # Install globally
22
+ npm install -g @quantracode/vibecheck
23
+
24
+ # Or use without installing
25
+ npx @quantracode/vibecheck scan --fail-on off --out vibecheck-scan.json
21
26
  ```
22
27
 
23
- ## Installation
28
+ ### Scan Another Folder
24
29
 
25
30
  ```bash
26
- npm install -g @quantracode/vibecheck
27
- # or
28
- pnpm add -g @quantracode/vibecheck
31
+ npx @quantracode/vibecheck scan --target ../my-other-app --out scan.json
29
32
  ```
30
33
 
31
34
  ## Usage
@@ -129,7 +132,9 @@ vibecheck view
129
132
  # Browser opens to http://localhost:3000 with results loaded
130
133
  ```
131
134
 
132
- ### Command Line Options
135
+ ## Command Line Options
136
+
137
+ ### Scan Options
133
138
 
134
139
  | Option | Description | Default |
135
140
  |--------|-------------|---------|
@@ -141,7 +146,6 @@ vibecheck view
141
146
  | `-e, --exclude <glob>` | Glob pattern to exclude (repeatable) | See below |
142
147
  | `--include-tests` | Include test files in scan | `false` |
143
148
  | `--emit-intent-map` | Include route map and coverage metrics | `false` |
144
- | `--changed` | Only scan changed files (not implemented) | `false` |
145
149
 
146
150
  ### Default Excludes
147
151
 
@@ -156,618 +160,93 @@ The following patterns are excluded by default:
156
160
  - `test/`, `tests/`, `fixtures/`, `__mocks__/`, `__fixtures__/`
157
161
  - `cypress/`, `e2e/`, `*.stories.*`
158
162
 
159
- ## Scanner Packs
160
-
161
- VibeCheck organizes security rules into modular scanner packs. Each pack focuses on a specific security domain.
162
-
163
- ### Auth Pack
164
-
165
- Rules for authentication and authorization issues.
166
-
167
- #### VC-AUTH-001: Unprotected State-Changing API Route
168
-
169
- **Severity:** High / Critical
170
- **Category:** auth
171
-
172
- Detects Next.js App Router API route handlers (POST, PUT, PATCH, DELETE) that perform database operations without authentication checks.
173
-
174
- **What it looks for:**
175
- - Route handlers in `app/**/route.ts` files
176
- - Handlers that use Prisma, Drizzle, or other database operations
177
- - Missing calls to `getServerSession`, `auth()`, or similar auth checks
178
-
179
- **Example (vulnerable):**
180
- ```typescript
181
- // app/api/users/route.ts
182
- export async function POST(request: Request) {
183
- const body = await request.json();
184
- await prisma.user.create({ data: body }); // No auth check!
185
- return Response.json({ success: true });
186
- }
187
- ```
188
-
189
- **Example (safe):**
190
- ```typescript
191
- // app/api/users/route.ts
192
- export async function POST(request: Request) {
193
- const session = await getServerSession();
194
- if (!session) {
195
- return Response.json({ error: "Unauthorized" }, { status: 401 });
196
- }
197
- const body = await request.json();
198
- await prisma.user.create({ data: body });
199
- return Response.json({ success: true });
200
- }
201
- ```
202
-
203
- ---
204
-
205
- #### VC-MW-001: Middleware Matcher Gap
206
-
207
- **Severity:** High
208
- **Category:** middleware
209
-
210
- Detects Next.js middleware that doesn't cover API routes, potentially leaving them unprotected.
211
-
212
- **What it looks for:**
213
- - `middleware.ts` files with `config.matcher` exports
214
- - Matchers that exclude `/api` routes
215
- - Projects using next-auth without middleware protection
216
-
217
- **Example (vulnerable):**
218
- ```typescript
219
- // middleware.ts
220
- export const config = {
221
- matcher: ['/dashboard/:path*'] // Missing /api routes!
222
- };
223
- ```
224
-
225
- **Example (safe):**
226
- ```typescript
227
- // middleware.ts
228
- export const config = {
229
- matcher: ['/api/:path*', '/dashboard/:path*']
230
- };
231
- ```
163
+ ## Scanner Categories
232
164
 
233
- ---
165
+ VibeCheck includes 30+ enforcement verification scanners across these categories:
234
166
 
235
- ### Validation Pack
167
+ ### Auth & Authorization
236
168
 
237
- Rules for input validation issues.
169
+ | Rule ID | Title | Severity |
170
+ |---------|-------|----------|
171
+ | VC-AUTH-001 | Unprotected State-Changing API Route | High/Critical |
172
+ | VC-MW-001 | Middleware Matcher Gap | High |
173
+ | VC-AUTH-010 | Auth-by-UI with Server Gap | Critical |
238
174
 
239
- #### VC-VAL-001: Validation Defined But Output Ignored
175
+ ### Input Validation
240
176
 
241
- **Severity:** Medium
242
- **Category:** validation
177
+ | Rule ID | Title | Severity |
178
+ |---------|-------|----------|
179
+ | VC-VAL-001 | Validation Defined But Output Ignored | Medium |
180
+ | VC-VAL-002 | Client-Side Only Validation | Medium |
243
181
 
244
- Detects cases where validation libraries (Zod, Yup, Joi) are called but the validated result is not used.
182
+ ### Network Security
245
183
 
246
- **What it looks for:**
247
- - Calls to `.parse()`, `.validate()`, `.parseAsync()`, etc.
248
- - Result not assigned to a variable
249
- - Raw `request.body` or `req.body` used after validation
184
+ | Rule ID | Title | Severity |
185
+ |---------|-------|----------|
186
+ | VC-NET-001 | SSRF-Prone Fetch | High |
187
+ | VC-NET-002 | Open Redirect | High |
188
+ | VC-NET-003 | Over-permissive CORS with Credentials | High |
189
+ | VC-NET-004 | Missing Request Timeout | Low |
250
190
 
251
- **Example (vulnerable):**
252
- ```typescript
253
- const schema = z.object({ name: z.string() });
254
- schema.parse(body); // Result ignored!
255
- await prisma.user.create({ data: body }); // Uses unvalidated body
256
- ```
257
-
258
- **Example (safe):**
259
- ```typescript
260
- const schema = z.object({ name: z.string() });
261
- const validated = schema.parse(body);
262
- await prisma.user.create({ data: validated });
263
- ```
191
+ ### Secrets & Config
264
192
 
265
- ---
193
+ | Rule ID | Title | Severity |
194
+ |---------|-------|----------|
195
+ | VC-CONFIG-001 | Undocumented Environment Variable | Low |
196
+ | VC-CONFIG-002 | Insecure Default Secret Fallback | Critical |
197
+ | VC-PRIV-003 | Debug Flags in Production | Medium |
266
198
 
267
- ### Privacy Pack
199
+ ### Privacy & Data
268
200
 
269
- Rules for data privacy and logging issues.
201
+ | Rule ID | Title | Severity |
202
+ |---------|-------|----------|
203
+ | VC-PRIV-001 | Sensitive Data Logged | High |
204
+ | VC-PRIV-002 | Over-broad API Response | Medium/High |
270
205
 
271
- #### VC-PRIV-001: Sensitive Data Logged
206
+ ### Cryptography
272
207
 
273
- **Severity:** High
274
- **Category:** privacy
208
+ | Rule ID | Title | Severity |
209
+ |---------|-------|----------|
210
+ | VC-CRYPTO-001 | Math.random for Tokens | High |
211
+ | VC-CRYPTO-002 | JWT Decode Without Verify | Critical |
212
+ | VC-CRYPTO-003 | Weak Password Hashing | High |
275
213
 
276
- Detects logging statements that include sensitive variable names.
214
+ ### File Uploads
277
215
 
278
- **What it looks for:**
279
- - `console.log`, `console.info`, `console.debug`, `logger.info`, etc.
280
- - Variables containing: password, secret, token, apiKey, creditCard, ssn, etc.
281
-
282
- **Example (vulnerable):**
283
- ```typescript
284
- console.log("User login:", { email, password }); // Logs password!
285
- ```
286
-
287
- **Example (safe):**
288
- ```typescript
289
- console.log("User login:", { email, timestamp: Date.now() });
290
- ```
216
+ | Rule ID | Title | Severity |
217
+ |---------|-------|----------|
218
+ | VC-UP-001 | File Upload Without Constraints | High |
219
+ | VC-UP-002 | Upload to Public Path | High |
291
220
 
292
- ---
221
+ ### Middleware
293
222
 
294
- ### Config Pack
223
+ | Rule ID | Title | Severity |
224
+ |---------|-------|----------|
225
+ | VC-RATE-001 | Missing Rate Limiting | Medium |
295
226
 
296
- Rules for configuration and secrets management issues.
227
+ ### AI Hallucinations
297
228
 
298
- #### VC-CONFIG-001: Undocumented Environment Variable
229
+ | Rule ID | Title | Severity |
230
+ |---------|-------|----------|
231
+ | VC-HALL-001 | Security Library Imported But Not Used | Medium |
232
+ | VC-HALL-010 | Comment Claims Protection But Unproven | Medium |
233
+ | VC-HALL-011 | Middleware Assumed But Not Matching | High |
234
+ | VC-HALL-012 | Validation Claimed But Missing/Ignored | Medium |
299
235
 
300
- **Severity:** Low
301
- **Category:** config
302
-
303
- Detects `process.env.VAR` references that aren't documented in `.env.example`.
304
-
305
- ---
306
-
307
- #### VC-CONFIG-002: Insecure Default Secret Fallback
308
-
309
- **Severity:** Critical
310
- **Category:** secrets
311
-
312
- Detects hardcoded fallback values for security-critical environment variables.
313
-
314
- **What it looks for:**
315
- - `process.env.VAR || "fallback"` patterns
316
- - Variables named: SECRET, KEY, TOKEN, PASSWORD, etc.
317
- - Hardcoded string fallbacks
318
-
319
- **Example (vulnerable):**
320
- ```typescript
321
- const jwtSecret = process.env.JWT_SECRET || "development-secret";
322
- ```
236
+ ### Supply Chain
323
237
 
324
- **Example (safe):**
325
- ```typescript
326
- const jwtSecret = process.env.JWT_SECRET;
327
- if (!jwtSecret) throw new Error("JWT_SECRET is required");
328
- ```
329
-
330
- ---
331
-
332
- ### Network Pack
333
-
334
- Rules for network security issues.
335
-
336
- #### VC-NET-001: SSRF-Prone Fetch
337
-
338
- **Severity:** High
339
- **Category:** network
340
-
341
- Detects fetch/axios calls where the URL is derived from user input without validation.
342
-
343
- **What it looks for:**
344
- - `fetch()` or `axios.get()` calls
345
- - URL constructed from request parameters, query strings, or body
346
- - No URL validation or allowlist checks
347
-
348
- **Example (vulnerable):**
349
- ```typescript
350
- export async function GET(request: Request) {
351
- const { searchParams } = new URL(request.url);
352
- const url = searchParams.get("url");
353
- const response = await fetch(url); // SSRF risk!
354
- return Response.json(await response.json());
355
- }
356
- ```
357
-
358
- **Example (safe):**
359
- ```typescript
360
- const ALLOWED_HOSTS = ["api.example.com", "cdn.example.com"];
361
-
362
- export async function GET(request: Request) {
363
- const { searchParams } = new URL(request.url);
364
- const url = searchParams.get("url");
365
- const parsed = new URL(url);
366
- if (!ALLOWED_HOSTS.includes(parsed.hostname)) {
367
- return Response.json({ error: "Invalid host" }, { status: 400 });
368
- }
369
- const response = await fetch(url);
370
- return Response.json(await response.json());
371
- }
372
- ```
238
+ | Rule ID | Title | Severity |
239
+ |---------|-------|----------|
240
+ | VC-SC-001 | Unpinned Dependencies | Medium |
241
+ | VC-SC-002 | Suspicious Postinstall Scripts | High |
242
+ | VC-SC-003 | Deprecated Packages | Low |
373
243
 
374
- ---
244
+ ### Abuse & Compute
375
245
 
376
- ### Hallucinations Pack
377
-
378
- Rules for detecting security libraries that are imported but not properly used.
379
-
380
- #### VC-HALL-001: Security Library Imported But Not Used
381
-
382
- **Severity:** Medium
383
- **Category:** middleware
384
-
385
- Detects security libraries (helmet, cors, csurf, etc.) that are imported but the import is never used.
386
-
387
- **What it looks for:**
388
- - Imports from security packages: helmet, cors, csurf, express-rate-limit, hpp, etc.
389
- - Import identifier not referenced after the import statement
390
-
391
- **Example (vulnerable):**
392
- ```typescript
393
- import helmet from "helmet"; // Imported but never used!
394
- import cors from "cors";
395
-
396
- const app = express();
397
- app.use(cors());
398
- // Missing: app.use(helmet());
399
- ```
400
-
401
- ---
402
-
403
- #### VC-HALL-002: NextAuth Imported But Not Enforced
404
-
405
- **Severity:** High
406
- **Category:** auth
407
-
408
- Detects next-auth imported but `getServerSession` never called, suggesting auth is configured but not enforced.
409
-
410
- **What it looks for:**
411
- - Imports from `next-auth` or `next-auth/next`
412
- - No calls to `getServerSession` anywhere in the file
413
-
414
- ---
415
-
416
- ## Phase 2 Rules
417
-
418
- ### Network Pack (Extended)
419
-
420
- #### VC-NET-002: Open Redirect
421
-
422
- **Severity:** High
423
- **Category:** network
424
-
425
- Detects server-side redirects where user-controlled input determines the destination.
426
-
427
- **Two-signal requirement:** Must identify user-controlled source AND redirect call uses that value.
428
-
429
- **Example (vulnerable):**
430
- ```typescript
431
- export async function GET(request: Request) {
432
- const { searchParams } = new URL(request.url);
433
- const next = searchParams.get("next");
434
- return NextResponse.redirect(next!); // Open redirect!
435
- }
436
- ```
437
-
438
- ---
439
-
440
- #### VC-NET-003: Over-permissive CORS with Credentials
441
-
442
- **Severity:** High
443
- **Category:** network
444
-
445
- Detects CORS configurations that combine `origin: "*"` with `credentials: true`.
446
-
447
- **Example (vulnerable):**
448
- ```typescript
449
- cors({ origin: "*", credentials: true }) // Dangerous combination!
450
- ```
451
-
452
- ---
453
-
454
- #### VC-NET-004: Missing Request Timeout
455
-
456
- **Severity:** Low
457
- **Category:** network
458
-
459
- Detects fetch/axios calls without timeout in API route handlers.
460
-
461
- **Example (vulnerable):**
462
- ```typescript
463
- const response = await fetch("https://external-api.com/data"); // No timeout!
464
- ```
465
-
466
- ---
467
-
468
- ### Middleware Pack
469
-
470
- #### VC-RATE-001: Missing Rate Limiting
471
-
472
- **Severity:** Medium
473
- **Category:** middleware
474
- **Confidence:** 0.65
475
-
476
- Detects unauthenticated state-changing endpoints without rate limiting.
477
-
478
- **What it looks for:**
479
- - POST/PUT/PATCH/DELETE handlers without auth checks
480
- - Handlers with database writes or sensitive operations
481
- - No rate limiting signals in handler or middleware
482
-
483
- ---
484
-
485
- ### Validation Pack (Extended)
486
-
487
- #### VC-VAL-002: Client-Side Only Validation
488
-
489
- **Severity:** Medium
490
- **Category:** validation
491
-
492
- Detects validation in frontend components but missing in API routes.
493
-
494
- ---
495
-
496
- ### Privacy Pack (Extended)
497
-
498
- #### VC-PRIV-002: Over-broad API Response
499
-
500
- **Severity:** Medium/High
501
- **Category:** privacy
502
-
503
- Detects Prisma queries returning full models without `select` restrictions.
504
-
505
- **Example (vulnerable):**
506
- ```typescript
507
- const users = await prisma.user.findMany(); // Returns password hash!
508
- return Response.json(users);
509
- ```
510
-
511
- **Example (safe):**
512
- ```typescript
513
- const users = await prisma.user.findMany({
514
- select: { id: true, name: true, email: true }
515
- });
516
- return Response.json(users);
517
- ```
518
-
519
- ---
520
-
521
- #### VC-PRIV-003: Debug Flags in Production
522
-
523
- **Severity:** Medium
524
- **Category:** config
525
-
526
- Detects `debug: true` or `dev: true` in config files without NODE_ENV guards.
527
-
528
- ---
529
-
530
- ### Crypto Pack
531
-
532
- #### VC-CRYPTO-001: Math.random for Tokens
533
-
534
- **Severity:** High
535
- **Category:** crypto
536
-
537
- Detects Math.random used to generate tokens, keys, or session IDs.
538
-
539
- **Example (vulnerable):**
540
- ```typescript
541
- const token = Math.random().toString(36).substring(2); // Predictable!
542
- ```
543
-
544
- **Example (safe):**
545
- ```typescript
546
- const token = crypto.randomBytes(32).toString('hex');
547
- ```
548
-
549
- ---
550
-
551
- #### VC-CRYPTO-002: JWT Decode Without Verify
552
-
553
- **Severity:** Critical
554
- **Category:** crypto
555
-
556
- Detects jwt.decode() used without jwt.verify() in the same file.
557
-
558
- **Example (vulnerable):**
559
- ```typescript
560
- const payload = jwt.decode(token); // Signature not verified!
561
- ```
562
-
563
- **Example (safe):**
564
- ```typescript
565
- const payload = jwt.verify(token, secret); // Signature verified
566
- ```
567
-
568
- ---
569
-
570
- #### VC-CRYPTO-003: Weak Password Hashing
571
-
572
- **Severity:** High
573
- **Category:** crypto
574
-
575
- Detects MD5/SHA1 for passwords or bcrypt with saltRounds < 10.
576
-
577
- **Example (vulnerable):**
578
- ```typescript
579
- crypto.createHash('md5').update(password).digest('hex'); // Weak!
580
- bcrypt.hash(password, 5); // Too few rounds!
581
- ```
582
-
583
- ---
584
-
585
- ### Uploads Pack
586
-
587
- #### VC-UP-001: File Upload Without Constraints
588
-
589
- **Severity:** High
590
- **Category:** uploads
591
-
592
- Detects file uploads without size or type validation.
593
-
594
- **Example (vulnerable):**
595
- ```typescript
596
- const file = formData.get('file') as File;
597
- // No size or type check before processing
598
- ```
599
-
600
- ---
601
-
602
- #### VC-UP-002: Upload to Public Path
603
-
604
- **Severity:** High
605
- **Category:** uploads
606
-
607
- Detects uploaded files written to public directories.
608
-
609
- **Example (vulnerable):**
610
- ```typescript
611
- fs.writeFileSync(`public/uploads/${filename}`, buffer); // Publicly accessible!
612
- ```
613
-
614
- ---
615
-
616
- ## Phase 3: Hallucination Detection Engine
617
-
618
- Advanced cross-file analysis for detecting security intent vs implementation gaps.
619
-
620
- ### Intent Command
621
-
622
- Generate a security intent map baseline for your codebase:
623
-
624
- ```bash
625
- # Generate intent map
626
- vibecheck intent ./my-project --out intent-map.json
627
-
628
- # Include intent map in scan output
629
- vibecheck scan ./my-project --emit-intent-map
630
- ```
631
-
632
- ### Hallucinations Pack (Phase 3)
633
-
634
- #### VC-HALL-010: Comment Claims Protection But Unproven
635
-
636
- **Severity:** Medium
637
- **Category:** hallucinations
638
- **Confidence:** 0.75
639
-
640
- Detects comments that claim security protection but the implementation doesn't prove it.
641
-
642
- **Example (vulnerable):**
643
- ```typescript
644
- // This route is protected by authentication middleware
645
- export async function POST(request: Request) {
646
- // No auth check here, and middleware doesn't cover /api routes
647
- await prisma.user.create({ data: body });
648
- }
649
- ```
650
-
651
- ---
652
-
653
- #### VC-HALL-011: Middleware Assumed But Not Matching
654
-
655
- **Severity:** High
656
- **Category:** hallucinations
657
- **Confidence:** 0.70
658
-
659
- Detects routes that expect middleware protection but are not covered by matcher patterns.
660
-
661
- **Example (vulnerable):**
662
- ```typescript
663
- // middleware.ts
664
- export const config = {
665
- matcher: ['/dashboard/:path*'], // Missing /api routes!
666
- };
667
-
668
- // app/api/users/route.ts
669
- // Auth handled by middleware (but middleware doesn't cover this!)
670
- export async function DELETE(request: Request) {
671
- await prisma.user.delete({ where: { id } });
672
- }
673
- ```
674
-
675
- ---
676
-
677
- #### VC-HALL-012: Validation Claimed But Missing/Ignored
678
-
679
- **Severity:** Medium
680
- **Category:** hallucinations
681
- **Confidence:** 0.80
682
-
683
- Detects validation that is claimed but not properly implemented or used.
684
-
685
- **Example (vulnerable):**
686
- ```typescript
687
- const schema = z.object({ name: z.string() });
688
- schema.parse(body); // Result ignored!
689
- await prisma.user.create({ data: body }); // Uses raw body
690
- ```
691
-
692
- ---
693
-
694
- #### VC-AUTH-010: Auth-by-UI with Server Gap
695
-
696
- **Severity:** Critical
697
- **Category:** auth
698
- **Confidence:** 0.85
699
-
700
- Detects client-side auth checks without corresponding server-side protection.
701
-
702
- **Example (vulnerable):**
703
- ```tsx
704
- // Client component
705
- const { session } = useSession();
706
- if (session) {
707
- // Only render if logged in
708
- await fetch('/api/users', { method: 'DELETE' }); // Server has no auth!
709
- }
710
- ```
711
-
712
- ---
713
-
714
- ### Coverage Metrics
715
-
716
- With `--emit-intent-map`, the scan artifact includes coverage metrics:
717
-
718
- - **authCoverage**: Percentage of state-changing routes with proven auth
719
- - **validationCoverage**: Percentage of routes with request bodies that have validation
720
- - **middlewareCoverage**: Percentage of routes covered by middleware matchers
721
-
722
- ### Intent Map Structure
723
-
724
- ```json
725
- {
726
- "routeMap": [
727
- {
728
- "routeId": "abc123",
729
- "method": "POST",
730
- "path": "/api/users",
731
- "file": "app/api/users/route.ts",
732
- "startLine": 10,
733
- "endLine": 25
734
- }
735
- ],
736
- "middlewareMap": [
737
- {
738
- "file": "middleware.ts",
739
- "matchers": ["/api/:path*"],
740
- "protectsApi": true,
741
- "startLine": 15
742
- }
743
- ],
744
- "intentMap": [
745
- {
746
- "intentId": "def456",
747
- "type": "AUTH_ENFORCED",
748
- "scope": "route",
749
- "source": "comment",
750
- "textEvidence": "// Protected by auth"
751
- }
752
- ],
753
- "proofTraces": {
754
- "abc123": {
755
- "routeId": "abc123",
756
- "authProven": true,
757
- "validationProven": false,
758
- "middlewareCovered": true,
759
- "steps": [...]
760
- }
761
- },
762
- "coverage": {
763
- "authCoverage": 0.85,
764
- "validationCoverage": 0.60,
765
- "middlewareCoverage": 1.0
766
- }
767
- }
768
- ```
769
-
770
- ---
246
+ | Rule ID | Title | Severity |
247
+ |---------|-------|----------|
248
+ | VC-ABUSE-001 | Unbounded AI API Calls | High |
249
+ | VC-ABUSE-002 | Missing Cost Controls | Medium |
771
250
 
772
251
  ## Output Formats
773
252
 
@@ -779,11 +258,11 @@ The default format, defined by `@vibecheck/schema`:
779
258
 
780
259
  ```json
781
260
  {
782
- "artifactVersion": "0.1",
261
+ "artifactVersion": "0.3",
783
262
  "generatedAt": "2024-01-15T10:30:00.000Z",
784
263
  "tool": {
785
264
  "name": "vibecheck",
786
- "version": "1.0.0"
265
+ "version": "0.3.2"
787
266
  },
788
267
  "summary": {
789
268
  "totalFindings": 2,
@@ -824,21 +303,79 @@ The default format, defined by `@vibecheck/schema`:
824
303
 
825
304
  ### SARIF Format
826
305
 
827
- [SARIF (Static Analysis Results Interchange Format)](https://sarifweb.azurewebsites.net/) is an OASIS standard for static analysis tools. Use `--format sarif` to generate SARIF 2.1.0 output, compatible with:
306
+ SARIF (Static Analysis Results Interchange Format) is an OASIS standard for static analysis tools. Use `--format sarif` to generate SARIF 2.1.0 output, compatible with:
828
307
 
829
- - **GitHub Code Scanning** - Upload via `github/codeql-action/upload-sarif`
830
- - **Azure DevOps** - Native SARIF support in security reports
831
- - **VS Code** - SARIF Viewer extension
832
- - **Other tools** - Any SARIF 2.1.0 compatible viewer
308
+ - **GitHub Code Scanning** Upload via `github/codeql-action/upload-sarif`
309
+ - **Azure DevOps** Native SARIF support in security reports
310
+ - **VS Code** SARIF Viewer extension
311
+ - **Other tools** Any SARIF 2.1.0 compatible viewer
833
312
 
834
313
  ```bash
835
314
  # Generate SARIF for GitHub Code Scanning
836
315
  vibecheck scan --format sarif --out results.sarif
316
+ ```
317
+
318
+ ## CI/CD Integration
319
+
320
+ ### GitHub Actions Example
837
321
 
838
- # Upload to GitHub (in CI workflow)
839
- - uses: github/codeql-action/upload-sarif@v2
840
- with:
841
- sarif_file: results.sarif
322
+ ```yaml
323
+ name: Security Scan
324
+
325
+ on: [push, pull_request]
326
+
327
+ jobs:
328
+ vibecheck:
329
+ runs-on: ubuntu-latest
330
+ steps:
331
+ - uses: actions/checkout@v4
332
+
333
+ - name: Setup Node.js
334
+ uses: actions/setup-node@v4
335
+ with:
336
+ node-version: '20'
337
+
338
+ - name: Run VibeCheck
339
+ run: npx @quantracode/vibecheck scan --format sarif --out results.sarif --fail-on high
340
+
341
+ - name: Upload SARIF
342
+ uses: github/codeql-action/upload-sarif@v3
343
+ if: always()
344
+ with:
345
+ sarif_file: results.sarif
346
+ ```
347
+
348
+ ### Policy Evaluation
349
+
350
+ Compare scans against baselines for regression detection:
351
+
352
+ ```bash
353
+ # Evaluate against startup profile
354
+ vibecheck evaluate \
355
+ --artifact vibecheck-scan.json \
356
+ --profile startup \
357
+ --out policy-report.json
358
+
359
+ # Compare against baseline (regression detection)
360
+ vibecheck evaluate \
361
+ --artifact vibecheck-scan.json \
362
+ --baseline main-branch-scan.json \
363
+ --profile enterprise
364
+ ```
365
+
366
+ Available profiles: `startup`, `growth`, `enterprise`
367
+
368
+ ## Intent Map & Coverage Metrics
369
+
370
+ With `--emit-intent-map`, the scan artifact includes coverage metrics:
371
+
372
+ - **authCoverage**: Percentage of state-changing routes with proven auth
373
+ - **validationCoverage**: Percentage of routes with request bodies that have validation
374
+ - **middlewareCoverage**: Percentage of routes covered by middleware matchers
375
+
376
+ ```bash
377
+ # Generate intent map
378
+ vibecheck scan ./my-project --emit-intent-map --out scan.json
842
379
  ```
843
380
 
844
381
  ## Architecture
@@ -847,57 +384,27 @@ vibecheck scan --format sarif --out results.sarif
847
384
  packages/cli/src/
848
385
  ├── commands/
849
386
  │ ├── scan.ts # Main scan orchestrator
387
+ │ ├── evaluate.ts # Policy evaluation
850
388
  │ └── explain.ts # Report viewer
851
389
  ├── scanners/
852
390
  │ ├── types.ts # ScanContext, types
853
391
  │ ├── helpers/
854
392
  │ │ ├── ast-helpers.ts # ts-morph utilities
855
393
  │ │ └── context-builder.ts # ScanContext factory
856
- │ ├── auth/
857
- ├── unprotected-api-route.ts # VC-AUTH-001
858
- │ └── middleware-gap.ts # VC-MW-001
859
- │ ├── validation/
860
- │ └── ignored-validation.ts # VC-VAL-001
861
- │ ├── privacy/
862
- │ └── sensitive-logging.ts # VC-PRIV-001
863
- │ ├── config/
864
- ├── undocumented-env.ts # VC-CONFIG-001
865
- │ └── insecure-defaults.ts # VC-CONFIG-002
866
- ├── network/
867
- │ │ └── ssrf-prone-fetch.ts # VC-NET-001
868
- │ └── hallucinations/
869
- │ └── unused-security-imports.ts # VC-HALL-001, VC-HALL-002
394
+ │ ├── auth/ # Auth & authorization scanners
395
+ │ ├── validation/ # Input validation scanners
396
+ ├── privacy/ # Privacy & data scanners
397
+ │ ├── config/ # Config & secrets scanners
398
+ ├── network/ # Network security scanners
399
+ │ ├── crypto/ # Cryptography scanners
400
+ ├── uploads/ # File upload scanners
401
+ │ ├── middleware/ # Middleware scanners
402
+ │ ├── hallucinations/ # AI hallucination scanners
403
+ ├── supply-chain/ # Supply chain scanners
404
+ └── abuse/ # Abuse & compute scanners
870
405
  └── index.ts
871
406
  ```
872
407
 
873
- ## Design Principles
874
-
875
- 1. **Deterministic** - No LLM calls, results are reproducible
876
- 2. **Local-only** - All analysis runs on your machine
877
- 3. **Low false positives** - Precision over recall
878
- 4. **Framework-aware** - Built for Next.js, Express patterns
879
- 5. **Schema-compliant** - Output conforms to `@vibecheck/schema`
880
-
881
- ## Adding New Scanners
882
-
883
- Each scanner must:
884
-
885
- 1. Accept a `ScanContext` with repo info and AST helpers
886
- 2. Return `Finding[]` conforming to the schema
887
- 3. Generate deterministic fingerprints for deduplication
888
- 4. Include clear evidence with file locations
889
-
890
- ```typescript
891
- import { type ScanContext } from "../types.js";
892
- import { type Finding } from "@vibecheck/schema";
893
-
894
- export async function scanMyRule(ctx: ScanContext): Promise<Finding[]> {
895
- const findings: Finding[] = [];
896
- // ... detection logic
897
- return findings;
898
- }
899
- ```
900
-
901
408
  ## License
902
409
 
903
410
  MIT
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- declare const CLI_VERSION = "0.3.1";
2
+ declare const CLI_VERSION = "0.3.2";
3
3
 
4
4
  export { CLI_VERSION };
package/dist/index.js CHANGED
@@ -547,7 +547,7 @@ function validateArtifact(json) {
547
547
  }
548
548
 
549
549
  // src/constants.ts
550
- var CLI_VERSION = "0.3.1";
550
+ var CLI_VERSION = "0.3.2";
551
551
 
552
552
  // src/utils/file-utils.ts
553
553
  import fs from "fs";
@@ -5725,7 +5725,7 @@ async function scanPostinstallScripts(context) {
5725
5725
  startLine: 1,
5726
5726
  endLine: 1,
5727
5727
  snippet: `"${scriptKey}": "${script.length > 100 ? script.slice(0, 100) + "..." : script}"`,
5728
- context: "Install script definition"
5728
+ label: "Install script definition"
5729
5729
  }
5730
5730
  ],
5731
5731
  remediation: {
@@ -5789,7 +5789,7 @@ async function scanVersionRanges(context) {
5789
5789
  startLine: 1,
5790
5790
  endLine: 1,
5791
5791
  snippet: `"${name}": "${version}"`,
5792
- context: `${isDevDep ? "devDependencies" : "dependencies"} - ${criticalInfo.reason}`
5792
+ label: `${isDevDep ? "devDependencies" : "dependencies"} - ${criticalInfo.reason}`
5793
5793
  }
5794
5794
  ],
5795
5795
  remediation: {
@@ -6076,7 +6076,7 @@ async function scanDeprecatedPackages(context) {
6076
6076
  startLine: 1,
6077
6077
  endLine: 1,
6078
6078
  snippet: `"${name}": "${version}"`,
6079
- context: isDevDep ? "devDependencies" : "dependencies"
6079
+ label: isDevDep ? "devDependencies" : "dependencies"
6080
6080
  }
6081
6081
  ],
6082
6082
  remediation: {
@@ -6158,7 +6158,7 @@ Detected packages:
6158
6158
  startLine: 1,
6159
6159
  endLine: 1,
6160
6160
  snippet: `"${pkgName}": "${allDeps[pkgName]}"`,
6161
- context: `${getGroupName(group)} authentication library`
6161
+ label: `${getGroupName(group)} authentication library`
6162
6162
  });
6163
6163
  }
6164
6164
  }
@@ -6294,7 +6294,7 @@ async function scanSuspiciousScripts(context) {
6294
6294
  startLine: 1,
6295
6295
  endLine: 1,
6296
6296
  snippet: `${name}@${pkg.version} (hasInstallScripts: true)`,
6297
- context: isDirect ? "Direct dependency" : "Transitive dependency"
6297
+ label: isDirect ? "Direct dependency" : "Transitive dependency"
6298
6298
  },
6299
6299
  ...scriptContent ? [
6300
6300
  {
@@ -6302,7 +6302,7 @@ async function scanSuspiciousScripts(context) {
6302
6302
  startLine: 1,
6303
6303
  endLine: 1,
6304
6304
  snippet: scriptContent.length > 200 ? scriptContent.slice(0, 200) + "..." : scriptContent,
6305
- context: "Install script content"
6305
+ label: "Install script content"
6306
6306
  }
6307
6307
  ] : []
6308
6308
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantracode/vibecheck",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Security scanner for modern web applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",