This is a sample audit report showing what a real Ubserve deep scan looks like. All data is fictional.
Start AuditThis is a sample report. Start an audit on your URL to see your own score. The scanner identified 5 findings — 1 critical, 1 high, 2 medium, and 1 low. Overall security posture is below recommended thresholds and requires immediate action on the critical issue before this app handles production traffic.
Row Level Security is disabled on the profiles table. Any authenticated user can read or overwrite records belonging to other users. This is a direct data exposure risk.
An exposed RPC function runs with elevated privileges and accepts unvalidated input, making it a potential vector for privilege escalation.
Storage buckets are correctly scoped. Auth email confirmation is enabled. No anonymous access was detected on sensitive endpoints.
3 tables (users, orders, messages) returned data without any login. Anyone can query them directly.
Authenticated requests can fetch other users' records by changing the ID in the request.
All write endpoints require a valid session. No unauthenticated writes were possible.
Content-Security-Policy and Strict-Transport-Security are missing from all responses.
Certificate is valid and expires in 187 days. TLS 1.2 and 1.3 are both supported.
The 'avatars' storage bucket is publicly readable. Files can be downloaded without logging in.
No service role key was found in any reachable frontend bundle or public file.
No API keys or environment variables were found exposed in publicly accessible JavaScript.
Anyone on the internet can query your database directly and download everything stored in it. Every user account, order, and message is publicly readable right now.
Someone who finds this can download your entire users list — every email, name, and account — without ever logging in. That means a stranger has more access to your users than your users do.
What happens if you do not fix this: someone may be able to pull customer records straight out of your database and use that data immediately against your users.
GET /rest/v1/users returned 847 rows with no Authorization header. Tables affected: users, orders, messages.
Open Cursor and paste this exactly: "You are fixing a production security issue in a Supabase + Next.js app. Issue: Database tables are publicly readable with no authentication. Evidence: GET /rest/v1/users returns all rows without an Authorization header. Tables affected: users, orders, messages. Task: 1. Go to Supabase dashboard → Table Editor → each affected table → enable Row Level Security. 2. Add a policy: allow select only where auth.uid() = user_id. 3. Test by making a request without an Authorization header — it should return 0 rows. 4. Explain the change in plain English. 5. List every table and policy you changed."
When logged in, a user can access another user's private information just by changing a number in the link. Your users' private data is not properly isolated.
A logged-in user can change other people's data — not just their own. They could view someone else's orders, billing details, or private messages.
What happens if you do not fix this: a logged-in user can view or change other people's data — not just their own.
GET /api/profile?userId=2 returned full profile while authenticated as userId=5. 847 user records accessible.
Open Cursor and paste this exactly: "You are fixing a production security issue in a Supabase + Next.js app. Issue: Authenticated users can access other users' data by changing the userId parameter. Evidence: GET /api/profile?userId=2 returns data for user 2 while the requester is user 5. Task: 1. Find every API route that accepts a userId, id, or similar parameter. 2. Add a server-side check that compares the param to the session user's ID. 3. Return a 403 if they don't match — never return another user's data. 4. List every file and route you changed. 5. Explain the fix in plain English."
Files your users uploaded — profile photos, documents — can be downloaded by anyone with the right link. No login is required.
Anyone who guesses or finds a file URL can download your users' private uploads — no account needed. This includes anything stored in that bucket.
What happens if you do not fix this: the weakness stays live in production and can turn into an avoidable incident later, when the fix is usually more expensive and more urgent.
Bucket 'avatars' is set to public read. 1,204 objects accessible without authentication.
Open Cursor and paste this exactly:
"You are fixing a production security issue in a Supabase + Next.js app.
Issue: The 'avatars' storage bucket is publicly readable.
Evidence: Objects can be downloaded without any Authorization header.
Task:
1. Go to Supabase dashboard → Storage → Buckets → avatars → set to Private.
2. Update the app to generate signed URLs using supabase.storage.from('avatars').createSignedUrl(path, 3600).
3. Replace any public URLs in the codebase with signed URL generation.
4. List every file changed.
5. Explain in plain English what changed and why."Without this protection attackers can more easily inject fake content into your pages and trick your users into giving up their login details.
Your app is missing a basic browser protection that stops attackers from injecting fake content into your pages. Without it, someone could trick your users into handing over their login details.
What happens if you do not fix this: the weakness stays live in production and can turn into an avoidable incident later, when the fix is usually more expensive and more urgent.
Content-Security-Policy header absent from all responses. Checked 12 routes.
Open Cursor and paste this exactly: "You are fixing a production security issue in a Next.js app. Issue: Content-Security-Policy header is missing from all responses. Evidence: 12 routes checked, none return a CSP header. Task: 1. Open next.config.js. 2. Add a headers() function that returns a Content-Security-Policy for all routes. 3. Start with: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'. 4. Adjust to match what your app actually loads. 5. Explain the change in plain English. 6. List the exact file changed."
Your app isn't telling browsers to always use a secure connection, making it easier for someone on the same network to intercept data.
Without this, browsers won't automatically upgrade connections to secure ones. Someone on the same Wi-Fi could potentially intercept traffic to your app.
What happens if you do not fix this: the weakness stays live in production and can turn into an avoidable incident later, when the fix is usually more expensive and more urgent.
Strict-Transport-Security header absent on all 12 sampled routes.
Open Cursor and paste this exactly:
"You are fixing a production security issue in a Next.js app.
Issue: Strict-Transport-Security header is missing.
Evidence: Not present on any of the 12 routes checked.
Task:
1. Open next.config.js.
2. Inside the headers() function, add: { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' } to all routes.
3. Confirm the header appears on a live response after deploying.
4. Explain the change in plain English.
5. List the exact file changed."Start with the fastest high-impact fixes first, then move into the lower-risk cleanup items.
Start in the Supabase dashboard and lock down each exposed table, then rerun the scan to confirm the data path is closed.
Add a server-side ownership check to every API route that returns user data. Verify requesting user matches resource owner before returning anything.
Switch the bucket to private and serve files via signed URLs — a 10-minute change in the Supabase dashboard.
One badge. More signups. Less churn.
Paste the snippet below on your site. It links to your live verification page and updates automatically with every rescan.
<a href="https://ubserve.com/verify/UB-AUD-2803-MYAPP"
target="_blank" rel="noopener noreferrer">
<img
src="https://ubserve.com/api/badge/UB-AUD-2803-MYAPP"
alt="Verified by Ubserve"
height="36"
/>
</a>Run this exact audit on your Supabase app and get a full report with evidence, AI fix prompts, and a shareable security badge.
Start Audit