Stripe secret key in bundle
sk_live_… or sk_test_… visible in any JS chunk.
Move all Stripe calls server-side. Rotate the key immediately. Audit recent charges.
The reference. Each entry below records what we look for, the severity, and the exact remedy. Every result page links into this document.
sk_live_… or sk_test_… visible in any JS chunk.
Move all Stripe calls server-side. Rotate the key immediately. Audit recent charges.
An AKIA-prefixed string in JS source.
Rotate via IAM. Use a Cognito identity pool or signed URLs for client-side access.
sk-… (forty characters or more) in client code.
Proxy LLM calls through your backend. Rotate the key. Cap usage limits.
A JWT with role:service_role decoded from a token in the bundle.
Bypasses all RLS. Rotate immediately. The service role should never leave the server.
A ghp_, gho_, ghu_, or ghs_ token in source.
Revoke the token. Use a server-side proxy for any GitHub API calls.
We decode the public anon key and surface project ref, role, issuer, expiry. Flagged as Medium if the key has expired.
No action when current. If expired, rotate the anon key in Supabase → Project Settings → API.
GET /rest/v1/ with the anon key returns the OpenAPI dump — the full list of tables and RPC functions.
Restrict introspection at the edge or in db.api.exposed_schemas. RLS still matters; this stops handing out the menu.
Anonymous key + GET on /rest/v1/<table> returns rows.
Enable RLS on the table and add SELECT policies that scope by auth.uid().
/storage/v1/bucket returns a non-empty array to anonymous clients.
Storage policies: remove anon SELECT on storage.buckets.
/auth/v1/settings indicates disable_signup is false.
If public signups are not intended, disable in Authentication → Providers → Email.
POST /rest/v1/rpc/<fn> with the anon key returns 200 or 400 (i.e. the function ran).
Revoke EXECUTE from anon, or rewrite the function as SECURITY INVOKER and audit it.
A transparency entry: how many tables and RPCs were tested, how many were denied, how many returned data.
No action; an honest record of what the scan tested.
Probe collections return 200 with no auth, or test writes succeed.
Replace if true with if request.auth != null plus per-document ownership checks.
Bucket discovery succeeds without authentication.
Storage rules: lock to request.auth != null and per-user paths.
Response missing the CSP header.
Add a CSP. Start in report-only mode while tuning.
No HSTS header on an HTTPS response.
Set Strict-Transport-Security: max-age=31536000; includeSubDomains.
CSP is set, but contains unsafe-inline, unsafe-eval, wildcard sources, or is missing key directives.
Drop unsafe-inline / unsafe-eval, replace wildcards with explicit origins, add object-src 'none' and frame-ancestors 'none'.
/.env returns content instead of a 404.
Block dotfiles at the CDN or hosting layer. Never deploy .env to a public directory.
*.js.map URLs serve full source.
Disable source-map output in production builds, or restrict access.
A curated subset. The scanner runs roughly thirty distinct checks across these families. More entries are being added.