Skip to main content
Application-layer security
B2B SaaS
セキュリティ
脆弱性診断
OWASP
認証・認可

A security checklist before real customer data goes into your SaaS — tenant isolation, keys, backups, and breach reporting

What a SaaS or web app team should verify before onboarding its first customers or migrating production data: two-tenant IDOR tests, key rotation, restore drills, PII-free logging, and Japan's breach-report duty to the PPC, each with the reason it has to happen before real data.

Published
Reading time
17 min read
Author
友田 陽大
Share

The short answer first. Before you put third-party real data — customers' personal information, transaction records — into a SaaS or web app, verify three things: other customers' and other users' data stays invisible, you can recover when something breaks, and you will notice and report a leak. None of these is the same question as whether the features are complete or the UI looks good, and nobody checks them unless someone does it on purpose.

This article is a checklist for startup and SMB development teams just before they onboard their first customer or migrate production data from an existing system. For each area it lists what to check and why it has to happen before real data, and it ends with a table of what to do a week before and the day before. The items are grounded in OWASP ASVS 5.0, the OWASP API Security Top 10 2023, the OWASP Top 10:2025, and each service's official documentation.

If you built your app with AI and can't read the code, Before you launch an app you built with AI is the better fit. If you are a solo developer who wants to harden things with free tools only, see the security checklist for personal projects. This article mainly targets B2B SaaS products that hold several customer companies' data in one system.


Why "before real data" is the line

Before real data, a hole you find is a fix item. After, it becomes a possible incident.

While no real data is in the system, you can swap keys or rebuild the database and nobody is affected. Find an authorization hole after real data is in, and fixing it is not the end of it. You have to investigate whether anyone saw data while the hole was open, explain it to customers where needed, and in some cases decide whether you must report to Japan's Personal Information Protection Commission (section 12). The same hole costs very different amounts depending on when it is found.


Before you hold real customer data

Web app & SaaS security audit — authorization, tenant isolation and config, verified in the code

1. Authorization and tenant isolation — hit "another company's data" with two tenants and two accounts each

The first thing to verify is that users of one tenant (customer company) can neither read nor write another tenant's data. In B2B SaaS, a break here is not one customer's problem but every customer's.

Number one in the OWASP API Security Top 10 2023 is API1:2023 Broken Object Level Authorization (BOLA): the flaw where swapping an ID returns someone else's data. ASVS 5.0 requires data-specific access restrictions against IDOR/BOLA in 8.2.2 and cross-tenant controls for multi-tenant applications in 8.4.1.

How to check. Create two tenants (company A and company B), each with two accounts (an admin and a regular member), and try the following:

  1. Log in as company A's member, and fetch, update, and delete a company B record by naming its ID directly.
  2. As company A's member, call the API for an action only company A's admin may perform (inviting users, viewing billing details, and so on).
  3. Put company B's tenant_id into the search filters or paging parameters of a list API.
  4. Check that none of company B's data slips into file download URLs, CSV exports, or the body of notification emails.
# A company-A member's token naming a company-B invoice ID directly. Expected result: 403 or 404
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: Bearer $TOKEN_TENANT_A_MEMBER" \
  "https://staging.example.com/api/invoices/$INVOICE_ID_OF_TENANT_B"

A button not appearing on screen proves nothing. As ASVS 8.3.1 puts it, authorization must be enforced at a trusted server-side layer, not by client-side JavaScript.

Why before real data. If this kind of flaw turns up after genuine customer data is in, the possibility that another company could see it remains. With only test data, it is just a bug. For the concrete verification steps on Supabase, see Verifying cross-tenant leaks — how to prove Supabase RLS isolation.


2. Authentication and sessions — are logged-out users and leavers really locked out?

Verify that old sessions and tokens can't be used after logout or account suspension. Everyone checks that login works; checking that lockout works is the step that gets skipped.

  • Session invalidation on logout: a token or cookie copied before logout must not call the API afterwards (ASVS 7.4.1). With self-contained tokens such as JWTs, check that the design doesn't leave them usable until expiry.
  • Ending all sessions on account deactivation: when a customer's staff member leaves and an admin suspends the account, all of that person's sessions end (ASVS 7.4.2).
  • New session on login: the session ID changes between before and after login (ASVS 7.2.4).
  • Brute-force defenses: you have decided and implemented how controls such as rate limiting handle password brute force and credential stuffing (ASVS 6.1.1, 6.3.1).
  • Password reset: reset links can't be reused, they expire, and a nonexistent email address gets the same response.

Why before real data. In B2B SaaS, transfers and departures on the customer side happen all the time. If customers pile up while lockout doesn't work, "people who left can still see it" persists until the fix ships.


3. Secrets and keys — rotate every key touched during development

Before real data goes in, replace every key that anyone may have touched during development and testing. You can't prove they never leaked, but swapping them now affects nobody.

This covers database passwords, cloud access keys, the payment provider's secret key and webhook signing secret, the email service's API key, admin-privileged keys such as service_role, JWT signing keys, and so on. During development there are endless paths: pasted into chat, read by an AI tool, a shared .env, known to a contractor whose engagement has ended.

  • Use production keys that differ from development and staging.
  • Keep keys out of source code and build artifacts, in a secrets management system (ASVS 13.3.1).
  • Give access to each key to as few as possible (ASVS 13.3.2).
  • Keep a list of which key is used where and how it is rotated (ASVS 13.1.4).
  • Run a secret scanner to confirm no keys remain in the Git history.

Why before real data. Rotating keys after real data is in means scheduling maintenance, notifying customers, and changing integration settings at the same moment. Right now, you just stop and swap.


4. Backups and restore drills — confirm "we restored it," not "it exists"

A backup only means something once you have actually restored it to a separate environment. And because backups hold the same data as production, restrict who can read them as tightly as the production database.

Even with managed services, check what is excluded. Supabase's backup documentation, for example, says:

  • Database backups don't include files stored through the Storage API (the database only holds their metadata).
  • Deleting a project permanently removes all associated data, backups included.
  • The project is inaccessible during a restore, and the larger the database, the longer the downtime.
  • Daily backups can still lose a day's worth of data, so if you need finer restore points, consider PITR (Point-in-Time Recovery).

Translate that to the services you use, and check:

  • Restore drill: actually restore a backup into an environment separate from production. Record how long it took and what didn't come back (files, state in external services, role passwords, and so on).
  • Agreed targets: decide how many hours of data loss are acceptable and how fast you recover, consistent with what you promise customers (terms of service, SLA).
  • Access to backups: keep the people who can download or restore backups to a minimum. Is every developer an admin on the dashboard?
  • Where dumps live: a pg_dump file on a laptop or a shared drive is itself a copy of real data leaving the system.

Why before real data. If the first time you run the restore procedure is in the middle of a production outage, any mistake in it becomes a second incident. Run it once while the data is empty, and you settle the procedure while breaking things costs nothing.


5. Logging — keep enough to investigate, without personal data

Logs need to hold enough to reconstruct when, where, who, and what, while keeping out sensitive data such as passwords, payment details, and tokens.

ASVS 5.0 asks in 16.2.1 for the metadata an investigation needs (when, where, who, what), and in 16.2.5 for logging that follows each data item's protection level (credentials and payment details not logged; session tokens hashed or masked). 16.3.1 and 16.3.2 also ask you to log authentication successes and failures and authorization failures.

  • Are you logging whole request bodies (leaving form input or the contents of uploaded CSVs behind)?
  • Are users' input values or headers (Authorization, cookies) being sent to your error-monitoring tool?
  • Are denied authorization attempts recorded? The cross-tenant attempts from section 1 go unnoticed unless they land here.
  • Have you decided who can read logs and how long they are kept? Logs become another place where personal data lives.

Why before real data. Fix the logging configuration after real data starts flowing, and the personal data already written stays in your log platform and in external monitoring services.


6. Deletion and retention — check that "it's gone when they cancel" is true

Decide which data is deleted when a customer cancels or a user asks for deletion, and confirm the deletion really reaches every place the data lives.

Data doesn't live only in the production database. It is copied into file storage, search indexes, analytics, logs, email-service lists, and backups. ASVS 14.2.7 asks for sensitive information to have a retention classification, with outdated or unnecessary data deleted automatically or on a defined schedule.

  • Do you have a procedure that deletes all of one tenant's data, and have you tested it once?
  • Are you relying only on soft deletes (a deleted flag) while the data itself remains?
  • Does the way you treat data that remains in backups match what your terms of service and privacy policy say?

Why before real data. Before data arrives, deletion can be built as part of the design. Added later, it becomes a hunt back through every place things were copied.


7. File storage — public buckets and signed-URL lifetimes

Confirm that the place uploaded files live isn't public by accident. Even with database authorization locked down, files are often served by a different mechanism.

In Supabase Storage, for example, files in a public bucket bypass access control for retrieval and serving, and anyone with the URL can read them. With S3 and other object storage, bucket policies and public settings need the same scrutiny.

  • Are customer documents, invoices, or identity documents sitting in a publicly configured location?
  • Is the expiry of time-limited (signed) URLs as short as the use case allows? Until it expires, anyone with the URL can open the file.
  • Can someone download a file by putting another tenant's ID into the path? (Run the section 1 check on files too.)
  • Are you displaying user-uploaded HTML or SVG from the same origin as your service?

For detailed design on Supabase Storage, and the holes RLS alone doesn't close, see Protecting Supabase Storage with RLS.

Why before real data. A misconfigured public setting is the kind of incident that keeps exposing data until someone notices. The Personal Information Protection Commission's page itself lists personal data made viewable on the internet through a system misconfiguration as an example of a reportable case (section 12).


8. Payments and webhooks — signature verification and duplicate processing

Confirm that notifications (webhooks) from your payment provider are processed only after their signature is verified, and that the same notification arriving more than once is processed only once.

Stripe's documentation states that every webhook event is signed in the Stripe-Signature header, and that an endpoint might receive the same event more than once. The official remedy is to log the event IDs you have processed and skip any already logged. In live mode, failed deliveries are retried with exponential backoff for up to 3 days.

  • Are you marking orders "paid" by trusting incoming JSON without verifying the signature?
  • If the same event arrives twice, does plan provisioning or billing run twice?
  • Are you heading into production with test keys and the test webhook secret still in place (section 3)?
  • Are you taking amounts or quantities from the client and using them for the charge as-is?

Why before real data. A payment bug becomes an incident requiring refunds and apologies the moment real money moves. While you are still in test mode, run through duplicated, failed, and out-of-order deliveries.


9. Admin access and least privilege — don't carry "everyone is an admin" into production

Keep the set of people with production admin rights minimal, and make what they did with those rights traceable afterwards. During development everyone tends to be able to do everything; the point is not to carry that into the environment holding real data.

  • Inventory the production admins in each console: cloud, database, payments, email, hosting. Are accounts of people who left, or contractors whose engagement ended, still there?
  • Require multi-factor authentication on admin consoles (ASVS 6.3.3).
  • Can a regular user's privileges reach internal admin features (for example a support screen that can view other tenants' data)?
  • Is viewing customer data for support purposes recorded?
  • Does the account your application uses to connect to the database hold only the privileges it needs (ASVS 13.2.2)?

Why before real data. Once privileges are broad, narrowing them requires finding out who uses what for which purpose. Starting minimal while the system is empty is far easier.


10. Dependencies and known vulnerabilities — let machines handle what machines can

Known vulnerabilities in dependencies can be detected mechanically by tools. Clear this with automation before spending human time.

In the OWASP Top 10:2025, software supply chain failures (A03:2025 Software Supply Chain Failures) are a category of their own.

  • List known vulnerabilities with your package manager's audit command or with Dependabot, and update the severe ones first.
  • Detect continuously in CI, so a newly disclosed vulnerability triggers a notification.
  • Confirm debug modes and stack-trace output are disabled in production (ASVS 13.4.2, 16.5.1).
  • Confirm the .git directory, API documentation, and monitoring endpoints aren't exposed externally by accident (ASVS 13.4.1, 13.4.5).

Why before real data. Dependency updates occasionally break behavior. Before real data, a break is something you notice and roll back.


11. Rate limits and abuse controls — can one user take the service down?

Confirm there are limits on count and volume for login, password reset, invitation emails, file upload, and any feature that calls an external API.

API4:2023 Unrestricted Resource Consumption covers APIs without limits leading to denial of service or higher operating costs. In SaaS, one tenant's usage can also degrade the experience of the others.

  • Do login and password reset limit the number of attempts?
  • Can features that send email or SMS be abused to spam third parties or burn money?
  • Are there limits on file size and count, and on data volume per tenant?
  • Have you set budget caps and alerts on pay-per-use external services (AI APIs, email, SMS)?

Why before real data. A limit is a line drawn before you know real usage: "beyond this, something is wrong." Introduce limits after customers start using the product and you risk blocking legitimate use.


12. Incident contacts and the duty to report to Japan's Personal Information Protection Commission

Decide before an incident who judges a suspected leak, whom they contact, and what gets reported within how many days. Business operators handling personal information in Japan have a duty to report certain leaks to the Personal Information Protection Commission (PPC).

According to the PPC's page on leak response and resources, private-sector operators must report a leak (or a possible leak) of personal data that falls under any of the following:

CategoryConditionExample given on the page
(1)Includes special care-required personal informationA leak of personal data including employees' health checkup results
(2)Risk of financial damage if misusedA leak of personal data including credit card numbers from an e-commerce site
(3)Caused by an act that may have had a wrongful purposeA leak through unauthorized access; a defaced website sending users' input to a third party
(4)More than 1,000 people affectedPersonal data made viewable on the internet through a system misconfiguration, affecting more than 1,000 people

The deadlines are a preliminary report within 3–5 days of discovery and a final report within 30 days of discovery. Where a wrongful purpose may be involved, the final report is due within 60 days of discovery. The page asks operators to report promptly once a leak is discovered. Note also that in industries where the PPC has delegated its authority to the minister in charge, the report goes to the delegated ministry rather than to the PPC.

What a SaaS development team should decide in advance:

  • Who judges a suspected leak, and their deputy.
  • The contact point and channel for each customer company. In B2B SaaS the customer company may itself be the party with the reporting duty, so notifying customers quickly matters especially.
  • How to use the logs from section 5 to establish since when, whose, and which data.
  • Contacts for outside experts (security and legal).

With a preliminary deadline of a few days, working out the process after an incident is too late.


What to do a week before and the day before

Finish the slow checks and changes a week before, and keep the day before for confirming that nothing has changed.

WhenWhat to doSection
A week beforeWith two tenants and two accounts each, try direct ID references, out-of-role APIs, and cross-tenant exports1
A week beforeConfirm old tokens can't act after logout or account suspension2
A week beforeReplace every key touched during development with new production values and disable the old ones3
A week beforeRun a full backup restore into a separate environment, recording the time taken and what didn't come back4
A week beforeConfirm logs and error monitoring don't contain input values, tokens, or payment details5
A week beforeRun a dependency audit and resolve severe known vulnerabilities10
A week beforeWrite down the incident owner, customer contacts, and outside experts' contacts12
The day beforeInventory production admin accounts, and disable test accounts and seeded admins9
The day beforeCheck storage public settings and signed-URL expiry7
The day beforeAfter switching payments to live mode, confirm webhook signature verification and duplicate prevention work with production settings8
The day beforeConfirm rate limits and budget alerts on pay-per-use services are active in production11
The day beforeConfirm the latest backup exists and the restore procedure document is somewhere you can open immediately4

Check it yourselves, or bring in a third party?

Most of the items in this article can be checked in-house. Three areas are where judgment splits: the correctness of authorization including tenant isolation, payments, and the handling of personal data. Deciding "may this person see this data" item by item against business rules is work that tool output alone can't settle. And the people who built a system tend to try it only in the ways they intended.

Even if you bring in a third party, running this checklist first lets the review spend its time on the parts that need design judgment. I take on third-party checks before real data goes in as a web application security audit; that page sets out what is and isn't examined and what each plan includes. To see the form the results arrive in, look at the sample pre-launch review report (a sample built on a fictional app).

If the founder isn't an engineer and first wants a sense of how risky the app is, the free 20-question self-check, which you can answer without reading code, is an easy place to start.


Summary

  • Before real data goes in, verify three things: other customers' and other users' data stays invisible, you can recover when something breaks, and you will notice and report a leak.
  • Tenant isolation comes first. With two tenants and two accounts each, confirm every direct ID reference is rejected.
  • Rotate every key touched during development, and confirm backups by restoring to a separate environment. Restrict access to backups as tightly as the production database.
  • Keep enough in logs to investigate without writing sensitive data. Design deletion to reach backups and logs as well.
  • When a leak meets certain conditions, reporting to the Personal Information Protection Commission is mandatory, and the preliminary report is due within 3–5 days of discovery. Decide the contact chain before an incident.

Every item here gets far more expensive once real data is in. Put the other way: running through it once now moves you a long way toward welcoming your first customer with confidence.

Frequently asked questions

How long does the pre-production check take?
It depends on scale, but if you run this checklist in-house, starting a week ahead and doing a final pass the day before is realistic. Three items take the time: the two-tenant authorization tests, key rotation, and the backup restore drill. Each is simple work, but they involve other people and configuration changes in external services, so they won't fit into the day before.
Can I carry the data we used in testing into production?
As a rule, don't. Test accounts, fixed passwords, and seeded admin users become entry points the moment they share a database with real data. Start production empty, load only the master data you need, and disable the admin accounts and API keys created during testing. If you want real data for testing, avoid copying production into a development environment.
If personal data leaks from our SaaS, must we always report it to Japan's Personal Information Protection Commission?
Not every leak. The Commission's page says reporting is mandatory when, among other cases, special care-required personal information is involved, there is a risk of financial damage, the leak may have been caused with a wrongful purpose, or more than 1,000 people are affected. The preliminary report is due within 3–5 days of discovery and the final report within 30 days (60 days where a wrongful purpose may be involved).
If we run a vulnerability scanner, do we still need this checklist?
Yes. Known vulnerabilities in dependencies and missing headers are what tools do well. Whether this user may see this tenant's data, though, is a question of business rules, and a tool that doesn't know them can't decide it. Tenant isolation, admin privileges, and duplicate payment handling need a person checking them against the specification.
Should a third-party review happen before or after real data goes in?
Before, if you can. Before, a hole that turns up is a fix item, not an incident, and rotating keys or rebuilding data affects no one. After, you also have to investigate whether real data was exposed while the hole was open, and possibly decide whether you have a duty to report.

References

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

Before you hold real customer data

Web app & SaaS security audit — authorization, tenant isolation and config, verified in the code

Beyond what tools catch, the design gap — who may touch which data — checked in the source code and configuration, with a prioritized fix plan. Not only Next.js / Supabase: web apps on Rails, Laravel, Django, Go and others, plus AWS / GCP / Vercel configuration. We never call anything “completely secure.”

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading