This report was produced by VibeAudit, an automated security and reliability scanner, operated by Volt, an AI agent. A human partner remains responsible for business ownership, production authorization, and any promised human review.
Confidential — prepared for the report recipient. Redistribution requires the owner’s permission.
vibeaudit.vip
Executive summary
Automated scan result with the overall score and finding counts by severity.
0/100
VibeScore
Grade F
Overall grade
critical
6
high
2
medium
6
low
0
info
1
Coverage
What this run could and could not observe. Zero findings never implies untested areas are safe.
FINDING 01Stripe live secret key exposed in repository
secrets
.env
sk_live_…y000 (29 chars)
Why it matters: A live Stripe secret key lets attackers issue refunds, change prices, and in the worst case drain your account.
How to fix: Roll the key in the Stripe dashboard right now, keep it server-side only, and switch to restricted keys with only the permissions each integration needs.
CRITICAL
FINDING 02OpenAI API key exposed in client code
secrets
src/lib/openai-client.ts
sk-proj-…r8s9 (46 chars)
Why it matters: Anyone visiting your app can read this key from the browser bundle and run up your OpenAI bill within minutes.
How to fix: Move the key to a server-side environment variable and proxy OpenAI calls through your backend or a Supabase Edge Function. Rotate the exposed key immediately at platform.openai.com.
CRITICAL
FINDING 03Supabase service_role key in client code
secrets
src/lib/supabase.ts
eyJhbGci…ghij (106 chars)
Why it matters: The service_role key bypasses all Row Level Security. In client code it means every visitor has full read/write access to every row in your database.
How to fix: The service_role key must live only in Edge Functions / server env. Use the anon key in the browser — RLS then enforces your access rules. Rotate the key in Supabase dashboard → Settings → API.
FINDING 04Table "orders" has no Row Level Security
database
supabase/migrations/0001_init.sql
CREATE TABLE orders — no matching "ENABLE ROW LEVEL SECURITY"
Why it matters: Without RLS, any visitor using the anon key can read, modify, or delete every row of "orders" — including other users' data. This is the single most common breach in Lovable/Bolt-built apps.
How to fix: Run: ALTER TABLE orders ENABLE ROW LEVEL SECURITY; then create policies restricting access per auth.uid(). If the table is meant to be public read-only, write an explicit FOR SELECT policy anyway.
FINDING 05OpenAI API called directly from browser code
abuse
src/lib/openai-client.ts
g) { const res = await fetch('https://api.openai.com/v1/chat/completions', {
Why it matters: Every visitor can replay this call with their own script — there is no server between the open internet and your metered API bill. One loop over this endpoint is a four-figure invoice.
How to fix: Proxy all OpenAI calls through a server function (Supabase Edge Function / API route) that holds the key in env vars, validates input, and rate-limits per user or per IP.
CRITICAL
FINDING 06OpenAI SDK bundled into client code
abuse
src/lib/openai-client.ts
'openai'
Why it matters: The SDK is designed for trusted server runtimes. Bundled to the browser it means the credential is in the visitor's hands and calls cannot be throttled or audited server-side.
How to fix: Move OpenAI SDK usage to an API route / Edge Function and call it from the frontend with your own session auth.
HIGH
FINDING 07Resend API key exposed in repository
secrets
.env
re_abcde…6789 (35 chars)
Why it matters: Same abuse pattern as SendGrid: phishing from your verified domain.
How to fix: Rotate in the Resend dashboard and send only from server code.
HIGH
FINDING 08Environment file ".env" committed with real values
config
.env
VITE_API_URL, RESEND_API_KEY, STRIPE_KEY
Why it matters: If this repo is ever pushed to GitHub or shared, every secret inside ships with it. Bots scan new public repos for .env files within minutes.
How to fix: Remove the file from git (git rm --cached), add it to .gitignore, rotate every key it contained, and distribute secrets via your hosting platform's env settings instead.
MEDIUM
FINDING 09No access policies found in the repository
database
Why it matters: Tables exist in migrations but no CREATE POLICY statements were found. Either policies live only in the Supabase dashboard (invisible to code review, lost on re-deploys) or data is unprotected.
How to fix: Move all RLS policies into versioned migration files so they are reviewable and reproducible.
Why it matters: Environment files with secrets can be committed by accident on the next "commit all".
How to fix: Add ".env" and ".env.*" to .gitignore (keep "!.env.example").
MEDIUM
FINDING 11Wildcard CORS (cors({ origin: "*" }))
config
api/server.js
Why it matters: Any website can make credentialed requests to your API from a visitor's browser. Combined with cookie auth this enables cross-site attacks.
How to fix: Restrict origins to your actual domains, e.g. origin: ["https://yourapp.com"]. Keep "*" only for fully public, credentialess endpoints.
Why it matters: Client-side route guards are cosmetic — the page source and any underlying API calls remain reachable. This flags routes that LOOK admin-only; confirm the backend actually enforces roles.
How to fix: Ensure every admin API endpoint checks the caller's role server-side (auth.uid() in RLS, or a role claim check in Edge Functions). Hide UI as a bonus, never as the mechanism.
Why it matters: Client-side route guards are cosmetic — the page source and any underlying API calls remain reachable. This flags routes that LOOK admin-only; confirm the backend actually enforces roles.
How to fix: Ensure every admin API endpoint checks the caller's role server-side (auth.uid() in RLS, or a role claim check in Edge Functions). Hide UI as a bonus, never as the mechanism.
MEDIUM
FINDING 14AI endpoints have no rate limiting anywhere in the repo
abuse
api/ai.js
AI calls in 1 server file(s); no rate-limit middleware found
Why it matters: A single scripted loop can burn your LLM budget or brute-force auth endpoints. Rate limiting is the one protection the AI tools never add for you.
How to fix: Add a per-IP/per-user limit on AI and auth routes (express-rate-limit, @upstash/ratelimit, or a Supabase Edge Function check against a counter table).
Why it matters: Recognized as a Lovable export. Audits are prioritized for this stack's signature defects.
How to fix: Top risk for Lovable apps: Supabase tables created without RLS, and access policies that exist only in the dashboard (lost on re-import). Fix RLS, then mirror every policy into supabase/migrations so it survives.