Ubserve
ubserve
Sample Audit Report
Sample only

This is a sample audit report showing what a real Ubserve deep scan looks like. All data is fictional.

Start Audit
UB-AUD-2803-MYAPP
myapp.com
C
Grade Security
Needs Attention
58
1Critical
2Medium
1High
1Low
APPmyapp.com
AUDIT IDUB-AUD-2803-MYAPP
TYPESecurity audit
DATEMar 28, 2025
SCANNERv1.4.0
DURATION4m 12s
Executive Summary

This 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.

Critical Vulnerabilities

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.

High Risk Findings

An exposed RPC function runs with elevated privileges and accepts unvalidated input, making it a potential vector for privilege escalation.

Safe / Low Risk

Storage buckets are correctly scoped. Auth email confirmation is enabled. No anonymous access was detected on sensitive endpoints.

What was checked

completed
Database access controls
fail

3 tables (users, orders, messages) returned data without any login. Anyone can query them directly.

User data isolation
fail

Authenticated requests can fetch other users' records by changing the ID in the request.

API login protection
pass

All write endpoints require a valid session. No unauthenticated writes were possible.

Browser security settings
fail

Content-Security-Policy and Strict-Transport-Security are missing from all responses.

Security certificate
pass

Certificate is valid and expires in 187 days. TLS 1.2 and 1.3 are both supported.

Uploaded file access
fail

The 'avatars' storage bucket is publicly readable. Files can be downloaded without logging in.

Master database key
pass

No service role key was found in any reachable frontend bundle or public file.

Secret keys in public code
pass

No API keys or environment variables were found exposed in publicly accessible JavaScript.

critical20–45 min

Your database has no access controls

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.

Evidence

GET /rest/v1/users returned 847 rows with no Authorization header. Tables affected: users, orders, messages.

Cursor fix prompt
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."
high20–45 min

Users can see each other's private data

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.

Evidence

GET /api/profile?userId=2 returned full profile while authenticated as userId=5. 847 user records accessible.

Cursor fix prompt
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."
medium10–20 min

Your uploaded files are publicly accessible

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.

Evidence

Bucket 'avatars' is set to public read. 1,204 objects accessible without authentication.

Cursor fix prompt
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."
medium5–10 min

Your app is missing a content protection setting

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.

Evidence

Content-Security-Policy header absent from all responses. Checked 12 routes.

Cursor fix prompt
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."
low5 min

Your app doesn't enforce secure connections

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.

Evidence

Strict-Transport-Security header absent on all 12 sampled routes.

Cursor fix prompt
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."

Fix order and expected effort

~25 min total w/ AI prompts

Start with the fastest high-impact fixes first, then move into the lower-risk cleanup items.

Fix 1~10 min w/ AI

Your database has no access controls

Start in the Supabase dashboard and lock down each exposed table, then rerun the scan to confirm the data path is closed.

Fix 2~10 min w/ AI

Users can see each other's private data

Add a server-side ownership check to every API route that returns user data. Verify requesting user matches resource owner before returning anything.

Fix 3~5 min w/ AI

Your uploaded files are publicly accessible

Switch the bucket to private and serve files via signed URLs — a 10-minute change in the Supabase dashboard.

Your customers need to know you take security seriously.

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.

C
Verifiedby Ubserve
Grade C · Score 58
Paste on your site
<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>
Save your report
Download a PDF or share a link.

Ready to audit your app?

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