guardvibe 3.0.45 → 3.0.47

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.
@@ -17,8 +17,22 @@ function parseSuppressionsFromCode(lines) {
17
17
  suppressions.push({ line: i + 2, ruleId });
18
18
  }
19
19
  else if (isCommentOnlyLine) {
20
+ // Comment-only line: suppress the comment's own line plus the next several
21
+ // lines, stopping early at a blank line or a new comment block. This makes
22
+ // suppress comments work for multi-line method chains (common Supabase / ORM
23
+ // builders span 3-5 lines from `.from(...)` through `.select(...).order(...)`).
20
24
  suppressions.push({ line: i + 1, ruleId });
21
- suppressions.push({ line: i + 2, ruleId });
25
+ for (let j = 1; j <= 5; j++) {
26
+ const nextLine = lines[i + j];
27
+ if (nextLine === undefined)
28
+ break;
29
+ const trimmed = nextLine.trim();
30
+ if (trimmed === "")
31
+ break;
32
+ if (/^\s*(?:\/\/|#|<!--)/.test(nextLine))
33
+ break;
34
+ suppressions.push({ line: i + 1 + j, ruleId });
35
+ }
22
36
  }
23
37
  else {
24
38
  suppressions.push({ line: i + 1, ruleId });
@@ -378,6 +392,12 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
378
392
  // for batch processing, not for serving to clients.
379
393
  if (rule.id === "VG955" && (isBatchScriptFile || isCronRoute))
380
394
  continue;
395
+ // Skip VG1006 (select('*') exposes columns) in batch/script paths — debug scripts,
396
+ // migrations, seeds, and fixtures run under service-role and write/log data
397
+ // server-side; '*' doesn't expose anything to a client. Application routes that
398
+ // do expose data still get flagged.
399
+ if (rule.id === "VG1006" && isBatchScriptFile)
400
+ continue;
381
401
  // Skip VG132 (Missing Request Body Size Limit) on Next.js route handlers and
382
402
  // pages/api endpoints — Next.js/Vercel apply a default 4.5MB body limit at the
383
403
  // platform layer, which is what the rule is checking for.
@@ -539,8 +559,14 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
539
559
  if (isMobileClient)
540
560
  continue;
541
561
  }
542
- // Skip VG448 (Supabase RPC bypass RLS) when using service_role key (server-side)
543
- if (rule.id === "VG448" && /(?:SUPABASE_SERVICE_ROLE|service_role|createServerSupabaseClient|createServerClient)/i.test(code))
562
+ // Skip VG448 (Supabase RPC bypass RLS) when the file is on a server-side codepath
563
+ // using a service-role / admin Supabase client. RLS bypass is intentional in those
564
+ // contexts and is identical in posture to direct .from(...).update(...) writes that
565
+ // already bypass RLS via the same key — flagging only .rpc() syntax produces FPs.
566
+ // Naming variants covered: createServerClient (Supabase docs), createServerSupabaseClient,
567
+ // createServiceClient / createServiceRoleClient (common project conventions),
568
+ // createAdminClient (Clerk-adjacent and DIY).
569
+ if (rule.id === "VG448" && /(?:SUPABASE_SERVICE_ROLE|service_role|createServerSupabaseClient|createServerClient|createService(?:Role)?Client|createAdminClient|createServiceSupabase)/i.test(code))
544
570
  continue;
545
571
  // VG872/VG873 legitimate package filtering is handled at match level below
546
572
  // Skip server-only import rule (VG964) for files that are inherently server-only:
@@ -668,6 +694,16 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
668
694
  if (/\.(?:order|range|limit)\s*\(/i.test(matched))
669
695
  continue;
670
696
  }
697
+ // Skip VG1006 (select('*') exposes columns) for count-only queries —
698
+ // .select('*', { count: 'exact', head: true }) returns only a row count, never
699
+ // materializes rows, so '*' doesn't expose any columns. The rule's pattern
700
+ // truncates at the `*` quote, so we look at the next ~120 chars for the head
701
+ // option (typical select(...) options object fits in that window).
702
+ if (rule.id === "VG1006") {
703
+ const tail = code.substring(match.index, match.index + (match[0].length + 120));
704
+ if (/\bhead\s*:\s*true\b/i.test(tail))
705
+ continue;
706
+ }
671
707
  // Skip VG155 (CSRF) in Next.js App Router route handlers (app/.../route.{ts,tsx,js,jsx}).
672
708
  // App Router protects state-changing requests by default: SameSite=Lax cookies block
673
709
  // cross-site cookie attachment, and JSON Content-Type triggers CORS preflight. Bearer-token
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardvibe",
3
- "version": "3.0.45",
3
+ "version": "3.0.47",
4
4
  "mcpName": "io.github.goklab/guardvibe",
5
5
  "description": "Security MCP for vibe coding. 365 rules, 36 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. Plus Next.js, Supabase, Clerk, Stripe, Prisma, tRPC, Hono, GraphQL, Convex, Turso, Uploadthing, AI SDK, and the full AI-generated stack.",
6
6
  "type": "module",