Trust Score ReportC74

01_demo_lovable

FIX recommended
Failures

6

Passed

13

Unknown

5

When

Mar 29, 02:20 PM

๐Ÿ‘ฅ Admin1/4

2 issues found

๐Ÿ’ฐ Billing4/8

2 issues found

๐Ÿ” Auth6/8

1 issue found

๐Ÿ›ก๏ธ Foundation2/4

1 issue found

Summary

24 checks analyzed, 6 failures. Estimated fix: ~8.0h. Recommended: fix the issues.

Fix Batches โ€” Recommended Order

1 issues in auth module. Start here.

Fix Batch 1: Auth Module (1 issues)

## AUTH-13 โ€” getUser() not getSession() for server-side auth
Issue: Client code uses getSession() (2 locations) but getUser() never called โ€” auth relies on unverified JWT
Affected files: src/contexts/AuthContext.tsx:38 โ†’ supabase.auth.getSession().then(({ data: { session } }) => {, src/pages/Billing.tsx:27 โ†’ const { data: { session } } = await supabase.auth.getSession();

Replace all server-side getSession() calls with getUser(). getSession() reads the JWT from local storage/cookies without server-side verification โ€” an attacker can forge the JWT. getUser() makes a round-trip to Supabase Auth server to verify the token cryptographically. In every API route, server action, and middleware: const { data: { user } } = await supabase.auth.getUser(); if (!user) return redirect('/login'); Client-side getSession() for UI state is acceptable, but all security decisions must use getUser().

Copy this prompt into your AI tool (Windsurf, Cursor, Lovable) to fix these issues.

Failed Checks (6)

AUTH-13criticalautofixneeds review

getSession() reads the JWT from cookies without server-side verification. An attacker can forge a JWT cookie and bypass auth. getUser() makes a round-trip to verify the token.

Show fix prompt
Issue: Client code uses getSession() (2 locations) but getUser() never called โ€” auth relies on unverified JWT
Affected files: src/contexts/AuthContext.tsx:38 โ†’ supabase.auth.getSession().then(({ data: { session } }) => {, src/pages/Billing.tsx:27 โ†’ const { data: { session } } = await supabase.auth.getSession();

Replace all server-side getSession() calls with getUser(). getSession() reads the JWT from local storage/cookies without server-side verification โ€” an attacker can forge the JWT. getUser() makes a round-trip to Supabase Auth server to verify the token cryptographically. In every API route, server action, and middleware: const { data: { user } } = await supabase.auth.getUser(); if (!user) return redirect('/login'); Client-side getSession() for UI state is acceptable, but all security decisions must use getUser().
ADM-02highneeds review

Admin pages (React routes) without auth guards are accessible to anyone who knows the URL. AI tools generate admin routes with client-side rendering but no server-side or middleware protection. Unauthenticated visitors can view admin dashboards, user lists, and sensitive data.

Show fix prompt
Issue: 2 admin pages without auth guard (no middleware coverage either)
Affected files: src/pages/AdminDashboard.tsx โ€” no auth guard detected, src/pages/AdminUsers.tsx โ€” no auth guard detected

Add an audit log for admin actions. Every admin action (user management, data changes, config updates) should be logged with: admin_id, action, target, timestamp, details. Create an audit_logs table and insert a record for each admin operation.
BIL-02highneeds review

Without constructEvent() signature verification, anyone can send fake webhook events. Attackers can grant themselves premium subscriptions or trigger refunds.

Show fix prompt
Issue: Webhook signature verification is conditional โ€” JSON.parse fallback bypasses constructEvent() when secret is missing
Affected files: supabase/functions/stripe-webhook/index.ts โ€” constructEvent() inside conditional, JSON.parse(body) fallback allows unverified webhooks

Add idempotency handling to your Stripe webhook. Store processed event IDs and skip duplicates. Use the event.id field: if (await isEventProcessed(event.id)) return; After processing: await markEventProcessed(event.id);
BIL-09highneeds review

If subscription status lives in localStorage or useState, users can manipulate it in browser DevTools. A user can set isPro: true and bypass paywalls.

Show fix prompt
Issue: Client-side billing state as source of truth (3 locations)
Affected files: src/pages/AdminDashboard.tsx:16 โ†’ supabase.from("subscriptions").select("plan"),, src/pages/AdminUsers.tsx:39 โ†’ supabase.from("subscriptions").select("id, user_id, plan"),, src/hooks/useSubscription.ts โ†’ Client hook reads billing table and derives plan/isPro locally

Move all billing state checks to the server side. Never trust client-side subscription status (localStorage, useState, or client-side Supabase reads). Create a server-side function that checks the subscriptions table using the service_role key or a server client: async function checkEntitlement(userId: string) { const { data } = await supabaseAdmin.from('subscriptions').select('status, plan').eq('user_id', userId).single(); return data?.status === 'active'; }. Call this function in every API route or server action that provides premium features.
CFG-01highautofix

Without strict: true, TypeScript allows implicit any, unchecked null access, and loose type assertions. AI tools generate code with any types extensively โ€” strict mode forces correctly typed code.

Show fix prompt
Issue: TypeScript strict mode not configured (defaults to false)
Affected files: tsconfig.json โ€” add "strict": true to compilerOptions

Enable TypeScript strict mode in tsconfig.json. Set "strict": true in compilerOptions. This enables: noImplicitAny, strictNullChecks, strictFunctionTypes, and other safety checks. Fix any resulting type errors โ€” they are real bugs that strict mode surfaces. AI tools generate better code when strict mode is enabled because they're forced to handle null/undefined explicitly.
ADM-08mediumautofix

Debug, seed, test, and internal routes left from development are accessible in production without auth. AI tools create routes like /api/seed, /api/reset, /admin/debug that bypass normal auth flows. These are the easiest targets for attackers.

Show fix prompt
Issue: 1 admin/debug route without auth check
Affected files: supabase/functions/seed-admin/index.ts โ€” no auth guard detected

Add rate limiting to admin endpoints. Admin operations like user management and data export should be rate-limited to prevent abuse. Limit to max 30 requests per minute for admin routes, with exponential backoff. Implement rate limiting at the server level (API route handler, Edge Function, or reverse proxy).
Passed Checks (13)
CLI v0.6.0Mode: trust-scoreSource: cli24 total checks

This is a static source-code analysis report. It is not a complete security audit. Results may contain false positives or miss certain issues. Always verify findings manually.