All guides

Before you launch

SaaS launch security checklist for vibe-coded apps

Check tenant isolation, Supabase RLS, sessions, Stripe webhooks, and public exposure before your SaaS launch, with a find, fix, and retest worksheet.

ScanMySaaS Editorial Team9 min readUpdated September 6, 2026

Before you send Product Hunt visitors or your first paying customers to a new SaaS, check what each person is allowed to do. A successful signup and checkout demonstrate the happy path. They do not show whether a different account can read a private document or unlock a paid feature without paying.

Use this vibe coding security checklist on an app you own or are authorized to test. It combines manual checks behind login with a review of the deployed public surface. Keep evidence for each result, fix the failures, and repeat the same checks on the release you intend to launch.

1. Prepare two test tenants and an anonymous session

Use a staging environment with production-like authorization settings and synthetic data. Create tenant A and tenant B, each with an account and a private test record. Add an ordinary member and an administrator when your app has roles. Keep a separate browser profile with no login. Use your own mailboxes and a Stripe sandbox; do not use customer records or real charges for these checks.

Write the expected permissions before testing. For example: an A member may read A's document, cannot read B's document, and cannot invite an administrator. A visitor with no session cannot access either private document. If cross-tenant sharing is intentional, record exactly which operation is allowed.

  • Record the environment, deployment or commit, test account roles, and synthetic record IDs.
  • Use separate browser profiles so switching accounts does not silently reuse the same session.
  • Mark each result Pass, Fail, Not tested, or Not applicable. Missing evidence is not a pass.

2. Test permissions at the request boundary

In your own test environment, use browser developer tools to inspect a request for a private record. While signed in as A, repeat the request with B's known test record ID. Check both the response and stored data: hiding a button or returning an error message is insufficient if the server still performs the action. OWASP recommends checking authorization on every request.

Repeat the check for reads, edits, deletes, exports, invitations, and role changes that your app supports. Test the ordinary member against administrator-only actions. Confirm the legitimate owner can still perform the intended operation; blocking everyone can make a broken feature look protected.

  • No session: private responses reveal no protected data and make no unauthorized changes.
  • Tenant A requesting B's record: the request is denied or returns no unauthorized rows; B's data stays unchanged.
  • Member requesting an admin action: the server checks current membership and role, independent of client-supplied IDs.
  • Owner performing an allowed action: the expected data is returned or changed successfully.

3. Check Supabase RLS through the real client path

If you use Supabase, review table grants and Row Level Security together. Exercise requests with the publishable or legacy anon key and no user session, then with each test user's session. Do not use an administrative SQL connection or a privileged server key to judge what a browser user can access. Test the roles and connection path the application actually uses.

Check SELECT, INSERT, UPDATE, and DELETE separately. For updates, test whether a user can change a row's owner or tenant; a policy must constrain the resulting row as well as the existing one. Verify policies against the deployed database rather than assuming a migration file reflects its current state.

  • Private tables: enable RLS and grant only the operations that the intended roles need.
  • Public content: confirm only the intended rows are readable and visitors cannot write them.
  • Privileged Supabase secret or service-role keys: keep them out of browser bundles and public environment prefixes.
  • Server routes using privileged clients: perform their own user, tenant, and role checks before querying.

4. Include files, sessions, and account changes

Use a harmless test file to check storage permissions. As A, try to read, overwrite, and delete B's private file through the app's normal API path. Inspect bucket visibility and storage policies separately from table policies. Public buckets are intended for public content; a hard-to-guess filename is not a private-file access control.

Exercise login, password reset, account switching, and logout with your test accounts. Confirm session cookies use appropriate Secure, HttpOnly, and SameSite settings where your authentication design uses cookies. Inspect actual network responses rather than relying on a dashboard screenshot.

  • After logout, confirm the client session is cleared and protected requests follow your documented token expiry and revocation behavior.
  • After removing a test member, verify that they lose the access your membership policy says should end.
  • Keep test tokens and reset links out of screenshots, shared reports, analytics, and coding-agent prompts.

5. Verify Stripe payments on the server

In a Stripe sandbox, complete one test purchase and confirm that the correct account receives the correct entitlement once. Opening a success URL or changing a browser-supplied plan must not independently grant paid access. Your server should verify the relevant Checkout Session and payment or subscription state; Stripe documents webhooks as necessary for reliable fulfillment.

Verify webhook signatures against the raw request body with the signing secret for that endpoint. Test an invalid signature and confirm it causes no entitlement change. The secret used by a local Stripe CLI listener can differ from the registered endpoint's secret.

  • Retry the same sandbox event and confirm credits or access are not granted twice, including concurrent processing.
  • Test relevant delayed, failed, and out-of-order events; an old event must not incorrectly restore or remove current access.
  • Close the browser before the success redirect and confirm the webhook still completes eligible fulfillment.
  • Keep test and live keys, webhook secrets, and customer records separate; inspect the configured live destination before launch.

6. Inspect the public deployment and record coverage gaps

Scan the final public hostname after deploying. ScanMySaaS can inspect observable signals such as headers, transport, cookies, and exposed files on reachable public pages. Its separate public GitHub scan reads a bounded set of files from the current tree for security-relevant patterns. It does not execute the repository or search full Git history; private repository support is not part of that public scan.

These checks cannot prove the tenant, RLS, storage, session-revocation, or Stripe entitlement tests above have passed. A repository hint about a missing policy is not a live authorization test. A clean public report is not security certification. Record untested boundaries explicitly and use the relevant platform checks and manual review alongside the report.

  • Confirm the hostname and deployed version match the app people will actually use.
  • For every finding, keep the affected location and redacted evidence; distinguish a verified exposure from a hardening recommendation.
  • After header or hosting changes, recheck signup, login, checkout, and external integrations for regressions.

7. Copy this find, fix, and retest worksheet

Create one entry per failed check in your issue tracker. The format below works for a manual authorization failure or an automated public finding. Keep raw tokens and private customer data out of the entry.

  • Find: environment and release; test actor and role; affected route, file, or object; expected result; actual result; redacted evidence.
  • Prioritize: what data or action is exposed; which users are affected; confirmed failure or unverified signal; owner and planned fix.
  • Fix: smallest reviewed change; deployment reference; rollback plan; any connected flows that need checking.
  • Retest: repeat the original failing request with the same test roles, then verify the legitimate user's allowed action still succeeds.
  • Record: retest time and release; new evidence; remaining gaps; Pass, Fail, or Not tested. Close only the check the evidence actually resolves.

Decide whether this release is ready for visitors

Treat unauthorized access to another tenant's data, exposed privileged credentials, and incorrect paid entitlements as launch blockers until they are contained and fixed. Give other verified findings an owner and an explicit decision. Do not make every missing hardening header look like the same level of risk.

Keep the worksheet with the release and rerun affected checks after changes to authentication, database policies, billing, hosting, or membership rules. The useful outcome is a repeatable check and evidence of the fix, not a one-time score.

Primary source

Check your production site

See which of these issues are visible now.

ScanMySaaS checks the public surface and keeps the affected URL with every finding. Verify results before changing production.

Run a free scan