Skip to content

Rule catalogue

What the Vibe Code Rescue Scan checks

Every check has a stable, versioned code (e.g. RSC-SEC-014) and its own page: what is checked, why it matters and what to do. The catalogue is the open reference behind the score.

Scan your own app for free

How the score is calculated

The score is not an opinion, it is arithmetic. Here it is in full — so you can retrace any result and disagree with us. The numbers on this page come straight from the running code, not from documentation that can go stale.

Dimension weights

Security
0.26
Privacy (GDPR)
0.20
Scaling & cost
0.14
Accessibility
0.12
Architecture & SEO
0.16
Code quality
0.12

Deductions per finding

Every dimension starts at 100 points. Each finding deducts, depending on severity:

High
34
Medium
16
Low
7
Info
0

Deductions from “low” findings are capped at 21 points per dimension. Hygiene items should lower the score but never flip the verdict on their own — eight missing HTTP headers are not a broken foundation.

From score to verdict

  • From 75 points, and with no evidenced security or privacy finding: go — the visible signals look sound. A single medium-severity finding in either area turns this into “iterate” even at a high score: a green light next to a finding the same report lists would be a contradiction.
  • 45 to 74 points: iterate — solvable work, in a clear order.
  • Stop is issued only when at least one finding has severity “high” — an evidenced high-risk result such as an open database or an exposed master key. A low score alone is not enough.

Whatever could not be assessed is marked “limited” and never counts as perfect. A dimension without findings is 100 only if the required scan tier actually ran.

Methodology version 2026.09. Every substantive rule change increments it, so older results stay interpretable.

Security

RSC-SEC-001high

No end-to-end HTTPS

Checks whether the final response is served encrypted or ends up on plain http.

RSC-SEC-002medium

HSTS header missing

Checks whether Strict-Transport-Security is set so even the first request is protected.

RSC-SEC-003medium

No Content-Security-Policy

Checks header and meta tag for a Content-Security-Policy as the main XSS mitigation.

RSC-SEC-004low

MIME sniffing not disabled

Checks whether `X-Content-Type-Options: nosniff` stops content-type guessing.

RSC-SEC-005low

No clickjacking protection

Checks X-Frame-Options or CSP `frame-ancestors` against embedding in foreign pages.

RSC-SEC-006info

CORS wildcard on the public document

Records `Access-Control-Allow-Origin: *` on HTML — not a flaw by itself, but a signal to check.

RSC-SEC-007info

Server technology disclosed

Records version headers such as `X-Powered-By` that make targeted exploit search easier.

RSC-SEC-008medium

Cookies without Secure/HttpOnly

Checks issued cookies for the Secure and HttpOnly flags.

RSC-SEC-009info

Supabase client configuration visible

Records project URL and anon key in the bundle — expected, but the starting point for access checks.

RSC-SEC-010high

Supabase service_role key in the client

Decodes JWTs in the bundle and reports the `service_role` claim, which bypasses RLS entirely.

RSC-SEC-011high

Secret key in shipped code

Searches for real secret patterns (Stripe, AWS, GitHub, PEM) in HTML and bundles.

RSC-SEC-012info

Firebase backend detected

Records Firebase configuration in the client — allowed; what matters are the security rules.

RSC-SEC-013high

.env file publicly retrievable

Requests known env paths and confirms hits by KEY=VALUE line signatures.

RSC-SEC-014high

.git directory public

Confirms a shipped `.git` via the signatures of `config` and `HEAD`.

RSC-SEC-015medium

Database tables granted to the anon role

Queries the schema endpoint with the client key the app publishes itself and lists the tables granted to the anon role — without fetching a row or a row count. Granted is not the same as readable: whether rows come out depends on Row Level Security.

RSC-SEC-028high

Database tables anonymously readable (proven)

Answers the actual question: do rows really come out with the publicly shipped key? Counting happens purely via the `Content-Range` header of a HEAD request — not a single row is fetched.

RSC-SEC-029medium

Google API key in the client

Records keys in `AIza…` format in shipped code — expected for Maps and Firebase, risky without a domain restriction.

RSC-SEC-030high

Database credentials visible in the client

Finds connection strings with embedded username and password in HTML or bundles.

RSC-SEC-031high

Firestore collections anonymously readable

Queries the collections the app names in its own bundle using the public web key — with `mask.fieldPaths=__name__`, so document names only, not a single field value.

RSC-SEC-032medium

Database functions callable by anonymous users

Lists the RPC functions granted to the anon role, read from the schema description — read, never called.

RSC-SEC-033medium

Signup open, accounts confirmed instantly

Reads the anonymously available auth configuration: self-signup open and email confirmation disabled.

RSC-SEC-034high

AI API called directly from the browser (statically proven)

Finds AI provider endpoints in shipped code. `high` with a matching key pattern in the same bundle, `medium` without.

RSC-SEC-035medium

Browser writes directly to the database

Finds write calls (`insert`, `update`, `upsert`, `delete`, storage upload) in shipped code or in `use client` files.

RSC-SEC-036high

Credentials compared in browser code

Finds comparisons such as `password === "…"` against a fixed literal in shipped code.

RSC-SEC-016medium

Storage buckets publicly listable

Checks whether file buckets hand out their object listing anonymously.

RSC-SEC-017high

Firebase database anonymously readable

Queries the Realtime Database endpoint with `shallow=true`: if it returns key names instead of “permission denied”, the database is open.

RSC-SEC-018high

Protected area guarded only in the browser

Detects admin/account routes the client router knows while the guard lives purely as a condition in the bundle — anyone with the URL gets in.

RSC-SEC-019medium

Role check inside the client bundle

Finds role comparisons such as `role === "admin"` in shipped JavaScript — trivially manipulated in the browser.

RSC-SEC-020medium

Access token in localStorage

Observes at runtime whether a JWT-like value ends up in web storage — readable via XSS.

RSC-SEC-021high

AI API called directly from the browser

Observes calls to LLM providers from the client — the required key is exposed and any visitor can generate on your bill.

RSC-SEC-022high

Backup or database dump public

Probes typical dump/backup paths and confirms hits via SQL or archive signatures.

RSC-SEC-023info

No Permissions-Policy

Checks whether camera, microphone and geolocation are explicitly restricted by header.

RSC-SEC-024low

No Referrer-Policy

Checks whether outgoing links leak internal URLs including query strings to third parties.

RSC-SEC-025medium

Unencrypted assets on an HTTPS page

Finds scripts, stylesheets or images embedded via `http://` on an https page.

RSC-SEC-026medium

Sign-in without a detectable limit

After ownership proof, sends a small series of failing sign-in attempts and checks whether anything throttles.

RSC-SEC-027high

Admin area reachable anonymously

Requests discovered admin paths anonymously and reports content instead of a redirect to sign-in.

RSC-SEC-050high

Tables without Row Level Security

Collects every `create table` and every `enable row level security` across all migrations and reports tables that are never protected.

RSC-SEC-051high

RLS policy allows everyone

Finds policies with `using (true)` — RLS is on but has no effect.

RSC-SEC-066high

RLS policy checks only that someone is signed in

Finds policies using `auth.role() = 'authenticated'` or `auth.uid() is not null` without binding to the row owner.

RSC-SEC-067high

RLS policy allows arbitrary writes

Finds `with check (true)` — the read condition may be strict while writes stay wide open.

RSC-SEC-068high

Edge function without JWT verification

Finds `verify_jwt = false` in `supabase/config.toml` — the server function is callable without signing in.

RSC-SEC-069high

Firebase rules allow everyone

Finds `allow …: if true` in `.rules` files — Firestore or Storage is wide open.

RSC-SEC-052high

service_role key in source code

Decodes JWTs in source files and reports the `service_role` claim.

RSC-SEC-053high

Secret key in source code

Searches source files for real secret patterns (Stripe, AWS, OpenAI, Anthropic, Slack, SendGrid, PEM).

RSC-SEC-054high

Database credentials in plaintext

Finds connection strings with embedded username and password.

RSC-SEC-055high

.env file committed

Detects a `.env` with real values in the source tree (not `.env.example`).

RSC-SEC-056medium

Supabase in use, schema not versioned

Reports Supabase in the code without migrations containing tables and RLS — access control then cannot be verified from the code.

RSC-SEC-057high

Secret exposed via a public env prefix

Finds variables with a public bundler prefix (`NEXT_PUBLIC_`, `VITE_`, `REACT_APP_`, `PUBLIC_`, `EXPO_PUBLIC_` …) whose name implies a secret — such values are compiled into the client bundle.

RSC-SEC-063high

Env file inside the shipped bundle

Detects a `.env` with real values among the files reconstructed from source maps — the build shipped it.

RSC-SEC-058high

Server Action without an access check

Inspects the body of every `"use server"` function that writes to the database and reports a missing identity check — server actions are public endpoints.

RSC-SEC-080high

Dependencies with a known vulnerability

Matches the repository's package versions against the public OSV database and names the affected packages with advisory IDs.

RSC-SEC-081high

Secret key in the Git history

Checks the added lines of recent commits against the same pattern list as the current tree — a deleted key stays readable.

RSC-SEC-082medium

Env file was in the repository and got removed

Reports environment files present in the checked history but missing from the current tree — the old values stay retrievable.

RSC-SEC-070high

Signed-in strangers read other people's records

After domain verification, creates a throwaway account and counts how many rows that stranger sees in personal-data tables — without fetching a single row.

RSC-SEC-071medium

Table fully readable by any signed-in user

Reports tables hidden from anonymous callers but fully visible to a freshly created stranger account — intended for catalogue data, the same flaw otherwise.

RSC-SEC-072info

Tenant isolation holds under test

Confirms that a freshly created account with no data of its own saw no rows in the tables checked.

RSC-SEC-073info

Cross-tenant check could not run

Records that no account could be created (signup closed or confirmation required) — tenant isolation stays unverified.

RSC-SEC-064high

Access check runs after the write

Compares the position of the auth call and the database write within the same function body and reports checks that happen after the write.

RSC-SEC-065high

Auth result is never evaluated

Reports functions that look up the identity but neither check the result nor bind it to the write — the call has no effect.

RSC-SEC-059high

API route without an access check

Finds route handlers with mutating methods that contain no authentication.

RSC-SEC-060medium

Input reaching the database unvalidated

Traces request bodies that flow into an insert or update without schema validation (mass assignment).

RSC-SEC-061high

Webhook without signature verification

Detects payment webhooks that process the payload without verifying the signature — anyone could fake a payment.

RSC-SEC-062medium

Unsanitised HTML rendered

Finds `dangerouslySetInnerHTML` with a dynamic value — the classic XSS path.