Sample report
Sample Security Report: Next.js + Supabase App
This is what NullFault returns after a passive scan. The target is a fictional app with mistakes we commonly see in Next.js and Supabase launches. Every panel below is the real report UI, including Markdown and PDF export.
Scan your own appScan report
completedhttps://launchpad-demo.example
sample-nextjs-supabase
Hardening Required
2 policy blockers detected under NullFault's passive policy — verify and resolve before launch.
NullFault inspected public responses, headers, TLS metadata, routes, and assets passively. These are reproducible HTTP/TLS observations, not proof of exploitability or a full business-risk verdict.
Policy gate applied 2 adjustments before scoring, including 1 launch blocker cleared.
- Policy blockers
- 2
- Critical
- 1
- Findings
- 6
- Checks run
- 31
Verify before launch
Highest severity
across 4 routes + 2 assets + 3 detection signals
24 returned clean
View deductions
100 - 63 = 37
- CriticalSupabase service_role key embedded in client JavaScript-35
- HighSupabase table `profiles` readable with the public anon key-20
- MediumAPI route reflects any Origin with credentials allowed-3
- MediumMissing Content-Security-Policy header-4
- LowPublic source maps reveal application source-1
Fix 2 blockers before launch, then work through the findings below.
Outside passive scan scope
These areas need owner-authorized active testing or product context before treating the launch verdict as complete security assurance.
- Rate-limit enforcement
- Auth bypass and authorization
- IDOR and tenant isolation
- Business logic abuse
- Payment or account permission flows
Configuration findings(4 priority + 2 low/info)
Supabase service_role key embedded in client JavaScript
Full database read/write access for any visitor.
Live credential exposure with full database privileges.
Why this matters
Potential risk chain
- 1. Unsafe script policy
- 2. Injected script can run if XSS exists
- 3. Browser data or tokens may be exposed
- 4. User account risk increases
Business impact
- Credential abuse
- Data access
- Emergency key rotation
Evidence snapshot
GET https://launchpad-demo.example/_next/static/chunks/app/admin/page-3f9c1a.js
Why confidence is High
- Verified from a live HTTP response
- Direct observation, not inferred
- High detector confidence
Supabase service_role key embedded in client JavaScript
Secret Exposure
Policy blockerCriticalA JWT with role service_role was found in a public Next.js chunk. The service_role key bypasses Row Level Security for every table.
Interpretation. Anyone who loads the page can copy the key and read, modify, or delete any row in the project, regardless of RLS policies.
Fix order: 1Risk reduction: HighEffort: QuickWhy now. Live credential exposure with full database privileges.
ImpactFull database read/write access for any visitor.
Recommended fixRotate the service_role key in Supabase now. Move every call that needs it into a server-only module (Route Handler or Server Action) and read it from a non-NEXT_PUBLIC_ environment variable.
Verify this finding
Copies the evidence-specific command for the exact URL, header, or pattern that triggered this claim.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Requested a curated public file path, suppressed SPA fallbacks, and redacted secret-like evidence when present.
Evidence
- EvidenceHigh detectionObserved
Found in /_next/static/chunks/app/admin/page-3f9c1a.js: createClient("https://abcd1234.supabase.co", "eyJhbGciOiJIUzI1NiIs…[redacted]") with payload {"role":"service_role"}- Method
- GET
- Final URL
- https://launchpad-demo.example/_next/static/chunks/app/admin/page-3f9c1a.js
- Observed
- 2026-10-28T09:14:00Z
Supabase table `profiles` readable with the public anon key
Supabase Exposure
Policy blockerHighA read-only REST request with the public anon key returned rows containing email addresses from the profiles table.
Interpretation. Row Level Security is disabled or a policy allows anonymous select on a table with personal data.
Fix order: 2Risk reduction: HighEffort: QuickWhy now. Observed anonymous access to personal data.
ImpactPersonal data of every user can be listed by anyone.
Recommended fixEnable RLS on public.profiles and add a select policy limited to auth.uid() = id. Re-run the scan to confirm the anonymous request returns no rows.
Verify this finding
Copies the evidence-specific command for the exact URL, header, or pattern that triggered this claim.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Matched the live response against NullFault's passive checks and stored the specific evidence that triggered this finding.
Evidence
- EvidenceHigh detectionObserved
GET https://abcd1234.supabase.co/rest/v1/profiles?select=id,email&limit=1 → 200, 1 row returned (email redacted)
- Method
- GET
- Final URL
- https://abcd1234.supabase.co/rest/v1/profiles
- Observed
- 2026-10-28T09:14:00Z
API route reflects any Origin with credentials allowed
CORS
Medium/api/account echoed an arbitrary Origin header in Access-Control-Allow-Origin together with Access-Control-Allow-Credentials: true.
Fix order: 3Risk reduction: MediumEffort: QuickImpactA malicious site may read authenticated responses if session cookies are sent cross-site.
Recommended fixReplace origin reflection with an explicit allowlist of your own domains in the route handler or middleware.
Verify this finding
Copies the evidence-specific command for the exact URL, header, or pattern that triggered this claim.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Sent safe OPTIONS preflight requests from untrusted origins and inspected the CORS response headers.
Evidence
- EvidenceMedium detectionObserved
OPTIONS /api/account (Origin: https://attacker.example) → Access-Control-Allow-Origin: https://attacker.example, Access-Control-Allow-Credentials: true
- Method
- OPTIONS
- Final URL
- https://launchpad-demo.example/api/account
- Observed
- 2026-10-28T09:14:00Z
Missing Content-Security-Policy header
HTTP Headers
MediumThe HTML response did not include a Content-Security-Policy header.
Fix order: 4Risk reduction: MediumEffort: ModerateImpactNo browser-level mitigation if an XSS bug is introduced later.
Recommended fixAdd a CSP in next.config headers() or middleware, starting with default-src 'self' and a nonce for scripts.
Verify this finding
Copies the evidence-specific command for the exact URL, header, or pattern that triggered this claim.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Inspected the live root response headers returned by the production target.
Evidence
- EvidenceHigh detectionObserved
GET / → 200, no Content-Security-Policy header
- Method
- GET
- Final URL
- https://launchpad-demo.example/
- Observed
- 2026-10-28T09:14:00Z
Raw relevant headers
- Content-Type
- text/html; charset=utf-8
- Strict-Transport-Security
- max-age=63072000
- X-Powered-By
- Next.js
Low priority improvements(2)
Public source maps reveal application source
Source Map Exposure
LowProduction JavaScript chunks reference .map files that are publicly downloadable.
Fix order: 5Risk reduction: LowEffort: QuickRecommended fixSet productionBrowserSourceMaps: false, or upload maps to your error tracker and delete them from the deployment.
Verify this finding
Copies the evidence-specific command for the exact URL, header, or pattern that triggered this claim.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Fetched public client assets and checked them for source maps, internal references, storage URLs, and credential patterns.
Evidence
- EvidenceHigh detectionObserved
GET /_next/static/chunks/main-app-81bd.js.map → 200 application/json (412 KB)
- Method
- GET
- Final URL
- https://launchpad-demo.example/_next/static/chunks/main-app-81bd.js.map
- Observed
- 2026-10-28T09:14:00Z
No DMARC record published
DNS and Email Auth
InfoNo TXT record was found at _dmarc.launchpad-demo.example.
Fix order: 6Risk reduction: LowEffort: QuickRecommended fixPublish "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain" and tighten to quarantine once reports look clean.
Fix prompt for your coding agent
Copies the finding, impact, fix, and affected locations as a ready-to-paste prompt for Copilot, Claude Code, or Cursor.
How we tested. Matched the live response against NullFault's passive checks and stored the specific evidence that triggered this finding.
Evidence
- EvidenceHigh detectionObserved
DNS TXT _dmarc.launchpad-demo.example → NXDOMAIN
What we checked(31)
Every detector NullFault ran against this target. A green cell means we inspected that surface and found nothing to report.
Check details
31 run · 24 passed · 4 checks flagged
Check details
31 run · 24 passed · 4 checks flaggedSecurity headers
Content Security Policy
PassivePassive onlyNo CSP absence, report-only, unsafe script, missing default-src, or broad connect-src finding was reported.
GET root response headers and CSP directive parsing.
No finding reportedHTTP Strict Transport Security
PassivePassive onlyNo missing HSTS finding was reported for the final HTTPS response.
GET root response headers on the final HTTPS response.
No finding reportedClickjacking protection
PassivePassive onlyNo missing clickjacking protection finding was reported from the root response headers.
Checked X-Frame-Options and CSP frame-ancestors on the root response.
No finding reportedMIME sniffing protection
PassivePassive onlyNo missing nosniff finding was reported from the root response headers.
Checked X-Content-Type-Options on the root response.
No finding reportedPermissions Policy
PassivePassive onlyNo missing Permissions-Policy finding was reported from the root response headers.
Checked Permissions-Policy on the root response.
No finding reported
Credential & Secret Exposure
Client bundle secret patterns
Deep ScanDeep evidenceNo private secret patterns were reported in inspected public JavaScript assets.
Fetched public JavaScript bundles and scanned them for private credential patterns.
No finding reportedInternal or debug references in bundles
Deep ScanDeep evidenceNo internal or debug endpoint reference finding was reported in inspected bundles.
Scanned public JavaScript bundles for internal, staging, local, admin, or debug endpoint references.
No finding reportedPublic secret files
Deep ScanDeep evidence1 finding reported: Supabase service_role key embedded in client JavaScript.
Requested curated public secret/config paths and suppressed SPA fallbacks.
FindingCriticalPublic source, cloud, database, or deployment config
Deep ScanDeep evidenceNo public source, provider config, database config, or deployment config finding was reported from curated path probes.
Requested curated source-control, package, provider config, and deployment config paths.
No finding reportedUnauthenticated sensitive API responses
Deep ScanSafe probeNo unauthenticated sensitive API response or API secret finding was reported from safe GET probes.
Sent safe unauthenticated GET probes to discovered and fallback API-like routes.
No finding reportedPublic storage buckets and objects
Deep ScanSafe probeNo public storage listing, sensitive object, reachable bucket, or storage secret finding was reported from inspected asset URLs.
Extracted public storage URLs from inspected bundles and used safe listing/object probes where URLs were present.
No finding reported
Privacy headers
Referrer Policy
PassivePassive onlyNo missing Referrer-Policy finding was reported from the root response headers.
Checked Referrer-Policy on the root response.
No finding reported
TLS
HTTPS and TLS protocol
PassivePassive onlyNo HTTPS availability, TLS metadata, or weak protocol finding was reported.
Inspected the final HTTPS response and negotiated TLS metadata.
No finding reportedCertificate expiry window
PassivePassive onlyNo certificate-expiry finding was reported within NullFault's warning windows.
Checked the observed leaf certificate expiry date.
No finding reported
Client assets
Public source maps
Deep ScanDeep evidence1 finding reported: Public source maps reveal application source.
Checked inspected JavaScript assets for inline or reachable production source maps.
FindingLow
Public exposure probes
Public API schemas or docs
Deep ScanDeep evidenceNo public OpenAPI, Swagger, or API documentation finding was reported from curated path probes.
Requested curated OpenAPI, Swagger, and API documentation paths.
No finding reportedDebug, management, or admin routes
Deep ScanDeep evidenceNo debug, management, or admin route exposure finding was reported from curated path probes.
Requested curated debug, metrics, management, and admin paths and matched response signatures.
No finding reported
API and browser access
CORS policy probes
Deep ScanSafe probe1 finding reported: API route reflects any Origin with credentials allowed.
Sent safe OPTIONS preflight requests from untrusted origins to root and discovered sensitive routes.
FindingMediumDangerous HTTP methods
Deep ScanSafe probeNo TRACE or unexpected write-method exposure finding was reported from OPTIONS probes.
Sent safe OPTIONS probes and inspected Allow and Access-Control-Allow-Methods headers.
No finding reportedPublic GraphQL endpoint
Deep ScanSafe probeNo publicly reachable GraphQL endpoint finding was reported from GraphQL probes.
Probed discovered GraphQL-like paths and common GraphQL fallback paths with safe GET requests.
No finding reported
Auth and session
Session cookies and auth responses
Deep ScanSafe probeNo session-cookie attribute, public auth response, or cacheable auth response finding was reported.
Inspected root Set-Cookie attributes and safely probed auth/session/current-user routes.
No finding reportedVerbose production error pages
Deep ScanDeep evidenceNo verbose framework error or stack-trace finding was reported from the missing-route probe.
Requested a randomized missing route and checked for framework debug output or stack traces.
No finding reported
Backend data exposure
Supabase public table reads
Deep ScanSafe probe1 finding reported: Supabase table `profiles` readable with the public anon key.
Looked for public Supabase client configuration and probed inferred table candidates with the anon key when present.
FindingHighFirebase Realtime Database public reads
Deep ScanNot assessedNo Firebase Realtime Database URL was observed in the recorded surface.
Looked for Firebase Realtime Database URLs in public client sources and safely probed detected database roots.
Not applicable
Availability and metadata
Reachability and HTTP metadata
PassiveSafe probeNo target access restriction, server-error, or HTTP metadata finding was reported.
Fetched the target with safe GET/httpx-style metadata probes and classified access or server-error responses.
No finding reported
Launch readiness
Vulnerability disclosure contact
PassivePassive onlyA readable security.txt file with the expected contact metadata was not reported as missing or incomplete.
Checked /.well-known/security.txt and /security.txt for security contact metadata.
No finding reportedIndexing and crawler posture
PassivePassive onlyNo noindex header, sensitive robots entry, or non-launch sitemap URL finding was reported.
Checked X-Robots-Tag, robots.txt, and sitemap.xml for noindex or non-launch URL signals.
No finding reported
Framework checks
Next.js launch posture
PassivePassive onlyNo public Next.js server manifest or client-visible non-launch URL finding was reported.
When Next.js was detected, checked for publicly reachable server manifests and client-visible non-launch URLs.
No finding reportedWordPress launch posture
PassiveNot assessedNo WordPress signal was observed in the recorded surface.
When WordPress was detected, checked XML-RPC, REST user enumeration hints, and default readme exposure.
Not applicableIIS launch posture
PassiveNot assessedNo IIS signal was observed in the recorded surface.
When IIS was detected, checked for the default IIS landing page and public web.config exposure.
Not applicableVercel deployment posture
PassivePassive onlyNo scanned Vercel deployment host or client-visible vercel.app reference finding was reported.
When Vercel was detected, checked whether the scanned host or client-visible links reference vercel.app deployment URLs.
No finding reported
AnalysisWhy this score and where to focus
Why this score and where to focus
Score lift by fix order
- Current score37
- Fix Supabase service_role key embedded in client JavaScript72
- Fix Supabase table `profiles` readable with the public anon key92
- Fix API route reflects any Origin with credentials allowed95
- Fix Missing Content-Security-Policy header99
Effort profile
- Under 10 min
- 0
- Under 30 min
- 0
- Longer fix
- 0
- Needs review
- 6
One fix can clear multiple findings
Backend data access policy
2 findingsOne configuration change may recover up to 55 readiness points.
- Supabase service_role key embedded in client JavaScript
- Supabase table `profiles` readable with the public anon key
Scan surface(6 scanned + 1 related host)
The verdict applies to the submitted target. Related same-domain hosts are scope signals to scan separately.
Rate limiting
InformationalPassive safe-request evidence only. No public rate-limit headers is not proof that rate limiting is absent. Enforcement cannot be confirmed without active testing.
No public headers observed
Rate limiting
InformationalPassive safe-request evidence only. No public rate-limit headers is not proof that rate limiting is absent. Enforcement cannot be confirmed without active testing.
routes requested under scanner safety limits
discovered routes without enforcement evidence
throttling responses observed
Safe responses lacked public rate-limit headers. This does not test enforcement.
- GEThttps://launchpad-demo.example/api/accountNo public headersMode: Passive
- POSThttps://launchpad-demo.example/api/checkoutNot assessedMode: Not assessed
Related surfaces detected(1)
Related surfaces detected(1)
- https://abcd1234.supabase.cobackendHighclient bundleDNS resolved
Routes discovered(4)
Routes discovered(4)
- GEThttps://launchpad-demo.example/200crawlpageAuth: Public ContentRisk: Low
- GEThttps://launchpad-demo.example/api/account401client bundleapiAuth: ProtectedRate: No Visible SignalRisk: Medium
Credentialed CORS reflection observed on this route.
- POSTtested OPTIONShttps://launchpad-demo.example/api/checkout204client bundleapiAuth: UnknownRate: UnknownRisk: Needs active validation
State-changing route; only safe methods were used.
- GEThttps://abcd1234.supabase.co/rest/v1/profiles200client bundledatabase apiAuth: Anonymous DataRisk: High
Anonymous request returned personal data.
Assets inspected(2)
Assets inspected(2)
- https://launchpad-demo.example/_next/static/chunks/app/admin/page-3f9c1a.jsapplication/javascript47 KB
- https://launchpad-demo.example/_next/static/chunks/main-app-81bd.jsapplication/javascript129 KB
How we adjusted findings(2)
The policy gate normalizes detector output so severities and launch blockers stay trustworthy. Every adjustment below is recorded for transparency.
Policy decisions(2)
Policy decisions(2)
- Policy blocker clearedpolicy-2026.10Missing Content-Security-Policy headerHTTP HeadersHighMediumPolicy blockerNot a blocker
NullFault cleared the policy-blocker flag because this finding class needs stronger proof before blocking release.
- Security-header quality is capped at High
- Defense-in-depth, not a policy blocker on its own
- Duplicate removedpolicy-2026.10Public source maps reveal application sourceSource Map Exposure
NullFault removed a duplicate so the same issue does not affect the report twice.
- Identical to another reported finding