Skip to content
ScanMyApp

Sample report

Sample audit report

This is what you receive: a report a non-developer can read, with a fix you can paste for every finding. The app below is fictional; the structure is exactly the one we deliver.

SCANMYAPP · AUDIT REPORTVERIFIED BY AN EXPERT

Notely (fictional app)

AI + human review · Next.js + Supabase · Commit 4f2a9c1

SECURITY SCORE58/100

Summary

  • critical2
  • high2
  • medium1
  • low1

Fix these 3 first

  1. Enable Row Level Security on the notes table (F1).
  2. Move the service_role key to the server and rotate it (F2).
  3. Check ownership in the notes API route (F3).

Findings

F1critical

Row Level Security disabled on the “notes” table

supabase/migrations/003_notes.sql:1

What’s wrong
The notes table was created without Row Level Security. Supabase exposes every table through its API, and your public key is in the browser.
Concrete risk
Anyone can read, edit or delete every user’s notes with a single request, without logging in.
Fix prompt

In supabase/migrations/003_notes.sql, the table "notes" has Row Level Security disabled. Create a new migration that enables RLS on this table and adds policies so users can only select, insert, update and delete their own rows (auth.uid() = user_id). Do not change any other table.

F2critical

Supabase service_role key used in client-side code

src/lib/supabaseAdmin.ts:4

What’s wrong
The service_role key bypasses every security rule. It is imported in a file that ends up in the browser bundle.
Concrete risk
Anyone who opens the browser developer tools gets full admin access to your database.
Fix prompt

In src/lib/supabaseAdmin.ts, the Supabase service_role key is used in code that is bundled for the browser. Move every use of this client to server-only code (route handlers or server actions), read the key from a server environment variable without the NEXT_PUBLIC_ prefix, and use the anon key in the browser. Then tell me to rotate the service_role key in the Supabase dashboard.

F3high

API route returns any user’s data without checking who is asking

src/app/api/notes/[id]/route.ts:12

What’s wrong
The route loads a note by the ID in the URL but never checks that it belongs to the logged-in user.
Concrete risk
A logged-in user can read other users’ notes by changing the ID in the URL.
Fix prompt

In src/app/api/notes/[id]/route.ts, the GET handler returns a note by id without checking ownership. Get the current user from the Supabase session, return 401 if there is none, and only return the note if note.user_id equals the user's id (404 otherwise). Do not change the response format.

F4high

Vulnerable dependency: outdated version of next

package.json:14

What’s wrong
The installed version of next has publicly known security advisories that are fixed in later releases.
Concrete risk
Known flaws are the first thing automated attacks look for.
Fix prompt

In package.json, upgrade next to the latest patch release of the major version currently used, run the install, and fix any breaking changes reported by the build. Do not upgrade other packages.

F5medium

No Content-Security-Policy header

next.config.ts

What’s wrong
Without a Content-Security-Policy, the browser will run any script injected into your pages.
Concrete risk
Turns a small injection bug into account takeover.
Fix prompt

In next.config.ts, add security headers for all routes: a Content-Security-Policy that only allows scripts from 'self' and the Supabase project URL, plus Referrer-Policy: strict-origin-when-cross-origin and X-Content-Type-Options: nosniff. List the domains you allowed so I can check them.

F6low

Source maps published in production

next.config.ts

What’s wrong
Production source maps let anyone read your original source code.
Concrete risk
Makes it easier for an attacker to find other weaknesses.
Fix prompt

In next.config.ts, make sure productionBrowserSourceMaps is false (or removed) so source maps are not published in production. Do not change anything else.

What was checked

  • Secrets and keys in the code and the Git history
  • Row Level Security on every table
  • Authentication and ownership checks on API routes
  • Known vulnerabilities in dependencies
  • Security headers and production build settings

What was not checked

  • Business logic not visible in the code (third-party dashboards, manual processes)
  • Infrastructure and hosting configuration
  • Behaviour of the live app under attack (no penetration testing)

Engineer’s recommendations

Included from $249
  1. Add a check to your deployment that fails if any public table has RLS disabled.
  2. Keep every privileged Supabase call in one server-only module so the key can’t leak again.
  3. Two false positives from the automated pass were removed after review.

Action plan

Fix F1 and F2 today, F3 and F4 this week, then F5 and F6. When you’re done, a re-scan gives you a before/after report with both scores side by side.

Analysis date: sample · Commit analysed: 4f2a9c1 · Score calculated by fixed rules from the severity of each finding. Automated audit verified by an engineer, not a security guarantee.

Want this for your app?

Request an express audit, or start with the free scan of your live URL.

Request the express audit

Results in secondsNo signupPassive checks only