Learn

Every issue VibeSafe finds — and how to fix it

When VibeSafe flags something in your code or app, this page explains what it means in plain English and shows you the exact fix. No security degree required. Bookmark it — it's your cheat sheet from scan to launch-ready.

What your safety score means

Every scan gives a score out of 100. It starts at 100 and drops for each issue found — the more severe, the bigger the drop.

Critical

Fix before you deploy. These are the exposed keys and open databases that end companies.

Warning

Fix before launch week. Bugs and weak spots that will bite you under real traffic.

Info

Fix when convenient. Best-practice and code-quality suggestions.

Passed

Things your code already does right — good habits worth keeping.

A score of 75+ is generally launch-ready with no criticals. Below 50 means something serious needs attention first.

The issues, explained

🔴 Exposed API keys & secrets 🔴 SQL injection 🔴 Missing database security (RLS) 🔴 Broken authentication 🔴 Cross-site scripting (XSS) 🟡 Missing Content-Security-Policy 🟡 Missing security headers 🟡 Missing await 🟡 Hallucinated packages 🟡 Logic bugs
Exposed API keys & secretsCritical
What it is

A live key, token, or password written directly in your code (e.g. sk_live_…, an AWS key, a database password).

Why it matters

Bots scan public code and deployed bundles for keys within minutes. A leaked Stripe or OpenAI key can rack up thousands in charges or expose customer data.

The fix
Beforeconst key = "sk_live_abc123..."
Afterconst key = process.env.STRIPE_SECRET_KEY

Move it to an environment variable, add .env to .gitignore, and rotate the exposed key at the provider — assume it's already compromised.

SQL injectionCritical
What it is

User input glued directly into a database query, so an attacker can inject their own SQL.

Why it matters

It's the classic way attackers dump or delete an entire database — or bypass your login screen entirely.

The fix
Beforedb.query("SELECT * FROM users WHERE id=" + req.query.id)
Afterdb.query("SELECT * FROM users WHERE id = $1", [req.query.id])

Always use parameterised queries — never build a query by concatenating user input.

Missing database security (RLS)Critical
What it is

A Supabase/Firebase table with no Row-Level Security, or with access enforced only in your frontend code.

Why it matters

The #1 cause of vibe-coded breaches. The public "anon" key ships in your app — without RLS, anyone can read every user's rows, not just their own. Frontend filters are a suggestion, not a rule.

The fix
SQLALTER TABLE todos ENABLE ROW LEVEL SECURITY;
SQLCREATE POLICY "own rows" ON todos FOR ALL USING (auth.uid() = user_id);

Enable RLS on every table and add a policy scoping rows to the logged-in user. Full RLS guide →

Broken authentication & access controlCritical
What it is

Missing auth checks, authorization enforced only in the browser, or inverted access logic (e.g. if (!isAdmin) where it should be if (isAdmin)).

Why it matters

Anyone can call your API directly, bypassing your UI. Client-side "protection" protects nothing.

The fix

Check the user's identity and permissions on the server for every sensitive action — never trust that the frontend hid a button.

Cross-site scripting (XSS)Critical
What it is

Rendering user-supplied content as raw HTML (e.g. innerHTML = userText), letting attackers inject scripts.

Why it matters

A malicious script running in your users' browsers can steal sessions, keystrokes, and data.

The fix
Beforeel.innerHTML = userComment
Afterel.textContent = userComment

Use textContent (or your framework's safe rendering) and sanitise any HTML you must render.

Missing Content-Security-PolicyWarning
What it is

No CSP header or meta tag on your deployed site. (This is the one in the screenshot most founders see first.)

Why it matters

CSP is a browser-level safety net: it blocks scripts and resources from origins you didn't allow, making XSS far harder to exploit if something ever slips through.

The fix

Add a CSP header in vercel.json or next.config.js. Start strict and loosen as needed. Vercel headers guide →

Missing security headersWarning
What it is

Absent headers like Strict-Transport-Security (HSTS), X-Frame-Options, or X-Content-Type-Options on your live site.

Why it matters

Each header blocks a class of attack — clickjacking, protocol downgrade, MIME sniffing — for a few lines of config.

The fix

Add them once in your host config. VibeSafe's live-website scan tells you exactly which are missing.

Missing awaitWarning
What it is

Calling an async function without await, so you get a Promise object instead of the actual result.

Why it matters

Your code runs but silently does the wrong thing — sending {} instead of real data, or saving nothing. These bugs are invisible until a user hits them.

The fix
Beforeconst user = db.query(...)
Afterconst user = await db.query(...)
Hallucinated packagesWarning
What it is

An import for a package that doesn't actually exist — AI tools sometimes invent plausible-sounding library names.

Why it matters

Beyond breaking your build, attackers register these fake names with malicious code ("slopsquatting") hoping you'll install them.

The fix

Verify every import exists on the real registry before installing. If you didn't ask for it and can't find its docs, remove it.

Logic bugsWarning
What it is

Code that runs but does the wrong thing: inverted conditions, off-by-one errors, == instead of ===, wrong comparison operators.

Why it matters

Non-technical founders can't spot these because they didn't write the code — but users feel them as "the app is acting weird."

The fix

VibeSafe points to the exact line and the corrected version. Re-scan after fixing to confirm.

Ready to find and fix these in your own app?

3 free scans every month · Your code is never stored