# SaaSに顧客の実データを入れる前のセキュリティチェックリスト — テナント分離・鍵・バックアップ・漏えい報告まで

> 初めての顧客を迎える前、本番データを移行する前に、SaaS／Webアプリで確認すべきセキュリティ項目を領域別に整理しました。2テナントでのIDOR検証、鍵のローテーション、復元訓練、PIIを出さないログ、個人情報保護委員会への漏えい等報告まで、なぜ実データの前なのかを添えて解説します。

- 公開日: 2026-10-12
- 著者: 友田 陽大
- タグ: B2B SaaS, セキュリティ, 脆弱性診断, OWASP, 認証・認可
- URL: https://tomodahinata.com/blog/saas-pre-production-data-security-checklist
- カテゴリ: アプリ層セキュリティ
- 総合ガイド: https://tomodahinata.com/blog/nextjs-supabase-application-security-guide

## 要点

- 実データを入れる前に確かめるのは「他社・他人のデータが見えない」「壊れても戻せる」「漏れたら気づいて報告できる」の3つ。機能の完成度とは別の軸で確認する
- 最優先はテナント分離。テナントを2つ、各テナントにアカウントを2つ用意し、相手側のIDを直接指定したリクエストがすべて拒否されることを確かめる（OWASP API Security Top 10 の API1:2023 BOLA）
- 開発中に触れた鍵（APIキー・DBパスワード・Webhookシークレット）は、実データの前にすべてローテーションする。漏れていない証明はできないが、入れ替えは今なら誰にも影響しない
- バックアップは「取れている」ではなく「別環境に戻せた」で確認する。誰がバックアップを読めるかも、本番DBと同じ重さで絞る
- 個人データの漏えい等が一定の要件に当たると、個人情報保護委員会への報告が義務になる。速報は発覚から3〜5日以内とされているので、連絡体制は事故の前に決めておく

---

結論から書きます。SaaSやWebアプリに第三者の実データ（顧客の個人情報・取引データ）を入れる前に確かめるべきことは、**「他社・他人のデータが見えないこと」「壊れても戻せること」「漏れたら気づいて報告できること」**の3つです。機能がそろっているか、画面がきれいかとは別の軸で、意図的に確認しなければ誰も確認しません。

この記事は、初めての顧客を迎える、あるいは既存システムから本番データを移行する直前のスタートアップ・中小企業の開発チームに向けたチェックリストです。領域ごとに「何を確認するか」と「なぜ実データの前なのか」を並べ、最後に前日と1週間前にやることを表にまとめました。項目の根拠は [OWASP ASVS 5.0](https://github.com/OWASP/ASVS)、[OWASP API Security Top 10 2023](https://owasp.org/API-Security/editions/2023/en/0x11-t10/)、[OWASP Top 10:2025](https://owasp.org/Top10/2025/) と、各サービスの公式ドキュメントです。

> コードが読めない立場でAIを使ってアプリを作った方は、[AIで作ったアプリを公開する前に — 非エンジニアのための本番リリース全ガイド](/blog/ai-app-pre-launch-guide-for-non-engineers)のほうが合っています。個人開発で無料ツールだけで固めたい方は[個人開発のセキュリティチェックリスト](/blog/personal-project-security-checklist-solo-dev-guide)を参照してください。この記事は、複数の顧客企業のデータを1つのシステムで預かる B2B SaaS を主な対象にしています。

---

## なぜ「実データを入れる前」が区切りなのか

実データの前なら、見つかった穴は「修正項目」で済みますが、後になると「事故の可能性」になるからです。

実データが入る前であれば、鍵を入れ替えてもデータベースを作り直しても、影響を受ける人はいません。ところが実データが入った後に認可の穴が見つかると、修正するだけでは終わりません。その穴が開いていた期間に誰かがデータを見た可能性を調べ、必要なら顧客に説明し、場合によっては個人情報保護委員会への報告が必要かを判断することになります（第12章）。同じ穴でも、見つかる時期によって対応コストがまったく違います。

---

## 1. 認可とテナント分離 — 2テナント×2アカウントで「他社のデータ」を叩く

最優先で確認すべきなのは、あるテナント（顧客企業）のユーザーが、他のテナントのデータを読めない・書けないことです。B2B SaaS では、これが破れると1社の問題ではなく全顧客の問題になります。

OWASP API Security Top 10 2023 の1位は [API1:2023 Broken Object Level Authorization（BOLA）](https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/)、つまり「IDを差し替えると他人のデータが返る」欠陥です。ASVS 5.0 も 8.2.2 でデータ単位のアクセス制限（IDOR/BOLA対策）を、8.4.1 でマルチテナントのテナント間制御を求めています。

**確認のしかた。** テナントを2つ（A社・B社）、それぞれにアカウントを2つ（管理者・一般）用意し、次を試します。

1. A社の一般ユーザーでログインし、B社のレコードのIDを直接指定して取得・更新・削除する
2. A社の一般ユーザーで、A社の管理者にしかできない操作（ユーザー招待、請求情報の閲覧など）のAPIを直接呼ぶ
3. 一覧APIの検索条件やページングのパラメータに、B社の `tenant_id` を入れてみる
4. ファイルのダウンロードURL、CSVエクスポート、メール通知の本文に、B社のデータが紛れ込まないか確かめる

```bash
# A社ユーザーのトークンで、B社の請求書IDを直接指定する。期待する結果は 403 か 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"
```

画面上でボタンが表示されないことは、確認になりません。ASVS 8.3.1 のとおり、認可はクライアント側のJavaScriptではなく、信頼できるサーバー側で強制されている必要があります。

**なぜ実データの前か。** この種の欠陥は、本物の顧客データが入ってから見つかると、その時点で「他社に見えていた可能性」が残るからです。テストデータしかない今なら、見えてもただのバグです。Supabase を使っている場合の具体的な検証方法は、[テナント越え漏洩を検証する — Supabase RLSの分離を『証明』する方法](/blog/supabase-multi-tenant-cross-tenant-leak-verification-guide)で詳しく扱っています。

---

## 2. 認証とセッション — ログアウトと退職者が本当に締め出されるか

確認すべきなのは、ログアウトやアカウント停止の後に、古いセッションやトークンで操作できないことです。ログインできることは誰でも確認しますが、締め出せることは確認が漏れがちです。

- **ログアウト後のセッション無効化**：ログアウト前にコピーしたトークンやCookieで、APIを呼べないこと（ASVS 7.4.1）。JWTのような自己完結型トークンでは、有効期限まで使えてしまう設計になっていないかを確認する
- **アカウント無効化時の全セッション終了**：顧客企業の担当者が退職し、管理者がアカウントを停止したら、その人の全セッションが終わること（ASVS 7.4.2）
- **ログイン時のセッション再発行**：ログイン前と後でセッションIDが変わること（ASVS 7.2.4）
- **総当たり対策**：パスワードの総当たりやリスト型攻撃に対し、レート制限などの対策がどう効くかを決めて実装していること（ASVS 6.1.1、6.3.1）
- **パスワードリセット**：リセット用のリンクが使い回せない、期限切れになる、存在しないメールアドレスでも同じ応答を返す

**なぜ実データの前か。** B2B SaaS では、顧客側の人事異動や退職が日常的に起きます。締め出しが効かない設計のまま顧客が増えると、修正までの間ずっと「辞めた人が見られる状態」が続きます。

---

## 3. 秘密情報と鍵 — 開発中に触れた鍵はすべてローテーションする

実データを入れる前に、開発・テスト中に誰かが触れた可能性のある鍵は、すべて新しいものに入れ替えてください。漏れていないことは証明できませんが、入れ替えは今なら誰にも影響しません。

対象になるのは、データベースのパスワード、クラウドのアクセスキー、決済サービスのシークレットキーとWebhook署名シークレット、メール送信サービスのAPIキー、`service_role` のような管理者権限キー、JWT署名鍵などです。開発中はチャットに貼った、AIツールに読ませた、`.env` を共有した、退職した外注先が知っている、といった経路がいくらでもあります。

- 本番の鍵は、開発・ステージングとは別の値にする
- 鍵はソースコードやビルド成果物に含めず、シークレット管理の仕組みに置く（ASVS 13.3.1）
- どの鍵を誰が使えるかを最小にする（ASVS 13.3.2）
- どの鍵がどこで使われていて、どうローテーションするかを一覧にしておく（ASVS 13.1.4）
- Gitの履歴に鍵が残っていないかを、秘密情報スキャンで確認する

**なぜ実データの前か。** 実データが入った後に鍵を入れ替えるには、メンテナンス時間を取り、顧客に告知し、連携先の設定を同時に変える必要があります。今なら、止めて差し替えるだけです。

---

## 4. バックアップと復元訓練 — 「取れている」ではなく「戻せた」を確認する

バックアップは、別環境に実際に復元できたことを確認して初めて意味を持ちます。そしてバックアップには本番と同じデータが入っているので、誰がそれを読めるかも本番DBと同じ重さで絞ります。

マネージドサービスでも、何が対象外かは確認が必要です。例えば [Supabase のバックアップのドキュメント](https://supabase.com/docs/guides/platform/backups)には、次のように書かれています。

- データベースのバックアップには、Storage API で保存したファイルは含まれない（DBにはファイルのメタデータしかないため）
- プロジェクトを削除すると、バックアップを含む関連データはすべて完全に削除される
- 復元中はプロジェクトにアクセスできなくなり、データベースが大きいほど停止時間が長くなる
- 日次バックアップでは最大1日分のデータを失い得るため、より細かい復元点が必要なら PITR（Point-in-Time Recovery）を検討する

ご利用のサービスに置き換えて、次を確認してください。

- **復元訓練**：本番とは別の環境に、実際にバックアップを戻してみる。かかった時間と、戻らなかったもの（ファイル、外部サービスの状態、ロールのパスワードなど）を記録する
- **目標の合意**：何時間分のデータ損失まで許容するか、何時間で復旧するかを、顧客との約束（利用規約・SLA）と矛盾しない形で決める
- **バックアップへのアクセス権**：バックアップのダウンロードや復元ができる人を最小にする。開発者全員がダッシュボードの管理者になっていないか
- **ダンプの置き場所**：手元のPCや共有ドライブに置いた `pg_dump` のファイルは、それ自体が実データの持ち出しになる

**なぜ実データの前か。** 復元手順を初めて試すのが本番障害の最中だと、手順の誤りがそのまま二次被害になります。データが空のうちに一度通しておけば、壊れても困らない状態で手順を固められます。

---

## 5. ログ — 調査に足りる情報を、個人情報なしで残す

ログには「いつ・どこで・誰が・何をしたか」を調査できるだけの情報を残し、パスワード・決済情報・トークンのような機微情報は残さない、という両立が必要です。

ASVS 5.0 は 16.2.1 で調査に必要なメタデータ（いつ・どこで・誰が・何を）を、16.2.5 でデータの保護レベルに応じたログ出力（認証情報や決済情報は記録しない、セッショントークンはハッシュ化やマスクをする）を求めています。16.3.1 と 16.3.2 では、認証の成功・失敗と、認可の失敗を記録することも求めています。

- リクエストボディをまるごとログに出していないか（フォームの入力内容、アップロードされたCSVの中身が残る）
- エラー監視ツールに、ユーザーの入力値やヘッダー（`Authorization`、Cookie）が送られていないか
- 認可で拒否された操作が記録されているか。第1章の越境の試みは、ここに残らないと気づけない
- ログを閲覧できる人と保存期間が決まっているか。ログもまた個人データの置き場所になる

**なぜ実データの前か。** 実データが流れ始めてからログ設定を直しても、それまでに出力された個人情報は、ログ基盤や外部の監視サービスにすでに残っています。

---

## 6. データの削除と保持期間 — 「解約したら消える」が本当かを確かめる

顧客が解約したとき、またはユーザーが削除を求めたときに、どのデータをいつ消すかを決め、その削除が本当にすべての置き場所に及ぶかを確認します。

データは本番DBだけにあるわけではありません。ファイルストレージ、検索インデックス、分析基盤、ログ、メール配信サービスのリスト、バックアップにも複製されます。ASVS 14.2.7 は、機微な情報に保持期間の分類を設け、不要になったデータを自動的に、または定めた周期で削除することを求めています。

- テナント単位で全データを削除する手順があり、一度テストしたか
- 論理削除（削除フラグ）だけで、実体が残り続けていないか
- バックアップに残るデータをどう扱うかを、利用規約やプライバシーポリシーの記載と一致させているか

**なぜ実データの前か。** 削除の仕組みは、データが入る前なら設計の一部として作れます。後から足すと、どこに何が複製されたかを遡って調べる作業になります。

---

## 7. ファイルストレージ — 公開バケットと署名URLの寿命

アップロードされたファイルの置き場所が、意図せず公開されていないことを確認します。データベースの認可を固めても、ファイルは別の仕組みで配信されていることが多いからです。

例えば Supabase Storage では、[公開バケット](https://supabase.com/docs/guides/storage/buckets/fundamentals)のファイルは読み取りと配信についてアクセス制御がバイパスされ、URLを持つ人は誰でも読めます。S3 などのオブジェクトストレージでも、バケットポリシーや公開設定の考え方は同様に確認が必要です。

- 顧客の書類・請求書・本人確認書類が、公開設定の置き場所に入っていないか
- 期限付きURL（署名URL）の有効期限は、用途に対して最小か。期限内はURLを持つ人が誰でも開ける
- ファイルのパスに、他テナントのIDを入れてダウンロードできないか（第1章と同じ確認をファイルにも行う）
- ユーザーがアップロードしたHTMLやSVGを、自社サービスと同じオリジンから表示していないか

Supabase Storage の場合の詳しい設計と、RLSだけでは塞がらない穴は[Supabase StorageをRLSで守る](/blog/supabase-storage-rls-access-control-bucket-folder-policies-guide)にまとめています。

**なぜ実データの前か。** 公開設定のミスは、気づくまでの間ずっと露出が続く種類の事故です。個人情報保護委員会のページでも、システムの設定ミスでインターネット上から個人データを閲覧できる状態になった例が、報告対象の例として挙げられています（第12章）。

---

## 8. 決済とWebhook — 署名検証と二重処理

決済サービスからの通知（Webhook）は、署名を検証してから処理し、同じ通知が複数回届いても一度しか処理しないことを確認します。

[Stripe のドキュメント](https://docs.stripe.com/webhooks)は、すべてのWebhookイベントに `Stripe-Signature` ヘッダーで署名していること、そしてエンドポイントが同じイベントを複数回受け取る可能性があることを明記しています。処理済みのイベントIDを記録し、記録済みのものは処理しない、というのが公式の対処です。本番環境では、失敗した配信は最長3日間、指数バックオフで再試行されます。

- 署名を検証せずに、届いたJSONを信じて「支払い完了」にしていないか
- 同じイベントが2回届いたら、プランの付与や請求が2回走らないか
- テスト用のキーとWebhookシークレットのまま本番を迎えていないか（第3章）
- 金額や数量をクライアントから受け取って、そのまま決済に使っていないか

**なぜ実データの前か。** 決済の不具合は、実際のお金が動いた時点で返金や謝罪が必要な事故になります。テストモードのうちに、重複・失敗・順不同の配信を一通り試しておきます。

---

## 9. 管理者アクセスと最小権限 — 「全員が管理者」を本番に持ち込まない

本番環境の管理者権限を持つ人を最小にし、その権限で何をしたかを後から追えるようにします。開発期間中は全員が何でもできる状態になりがちですが、それを実データの環境に持ち込まないことが要点です。

- クラウド、データベース、決済、メール、ホスティングの各管理画面で、本番の管理者を棚卸しする。退職者や契約が終わった外注先のアカウントが残っていないか
- 管理画面には多要素認証を必須にする（ASVS 6.3.3）
- 社内向けの管理機能（他テナントのデータを見られるサポート用画面など）に、一般ユーザーの権限で到達できないか
- サポート目的で顧客データを閲覧した操作が、記録に残るか
- アプリケーションがDBに接続するアカウントは、必要な権限だけを持っているか（ASVS 13.2.2）

**なぜ実データの前か。** 権限は一度広げると、狭めるときに「誰が何に使っているか」の調査が必要になります。空のうちに最小で始めるほうが、はるかに簡単です。

---

## 10. 依存関係と既知の脆弱性 — 機械に任せられる部分は機械に任せる

依存パッケージの既知の脆弱性は、ツールで機械的に検出できます。ここは人の時間をかける前に自動化で片づけます。

OWASP Top 10:2025 では、ソフトウェアサプライチェーンの失敗（A03:2025 Software Supply Chain Failures）が独立した項目になっています。

- パッケージマネージャーの監査コマンドや Dependabot などで、既知の脆弱性を一覧にし、重大なものから更新する
- CIで継続的に検出し、新しい脆弱性が見つかったら通知が来るようにする
- 本番でデバッグモードやスタックトレースの表示が無効になっているか（ASVS 13.4.2、16.5.1）
- `.git` ディレクトリやAPIドキュメント、監視用エンドポイントが、意図せず外部に公開されていないか（ASVS 13.4.1、13.4.5）

**なぜ実データの前か。** 依存の更新は、まれに挙動を壊します。実データが入る前なら、壊れても気づいて戻すだけで済みます。

---

## 11. レート制限と濫用対策 — 1人のユーザーがサービスを止められないか

ログイン、パスワードリセット、招待メール送信、ファイルアップロード、外部APIを呼ぶ機能に、回数や量の上限があることを確認します。

[API4:2023 Unrestricted Resource Consumption](https://owasp.org/API-Security/editions/2023/en/0xa4-unrestricted-resource-consumption/) が扱うのは、上限のないAPIがサービス停止や運用コストの増大につながる問題です。SaaS では、1つのテナントの使い方が他のテナントの体験を悪化させることもあります。

- ログインとパスワードリセットに、試行回数の制限があるか
- メールやSMSを送る機能が、第三者への迷惑メール送信や費用の浪費に使われないか
- ファイルのサイズと件数、1テナントあたりのデータ量に上限があるか
- 従量課金の外部サービス（AI API、メール、SMS）に、予算の上限とアラートを設定しているか

**なぜ実データの前か。** 上限は、実際の利用量を知る前に「これ以上はおかしい」という線を引いておくものです。顧客が使い始めてから上限を入れると、正当な利用を止めてしまう恐れがあります。

---

## 12. インシデント時の連絡先と、個人情報保護委員会への報告義務

漏えいが疑われたときに、誰が判断し、誰に連絡し、何日以内に何を報告するかを、事故の前に決めておきます。日本の個人情報取扱事業者には、一定の漏えい等について個人情報保護委員会への報告義務があります。

[個人情報保護委員会の「漏えい等の対応とお役立ち資料」](https://www.ppc.go.jp/personalinfo/legal/leakAction/)によれば、民間事業者に報告が義務付けられるのは、次のいずれかに当たる個人データの漏えい等（またはそのおそれ）です。

| 区分 | 内容 | ページに挙げられている例 |
|---|---|---|
| (1) | 要配慮個人情報が含まれる | 従業員の健康診断等の結果を含む個人データの漏えい |
| (2) | 不正に利用されると財産的被害が生じるおそれがある | ECサイトからのクレジットカード番号を含む個人データの漏えい |
| (3) | 不正の目的をもって行われたおそれがある行為による | 不正アクセスによる漏えい、ウェブサイトの改ざんで入力情報が第三者に送信された場合 |
| (4) | 本人の数が1,000人を超える | システムの設定ミス等でインターネット上から閲覧可能になり、1,000人を超える場合 |

報告の期限は、**速報が発覚日から3〜5日以内、確報が発覚日から30日以内**です。不正な目的で行われたおそれがある場合、確報は発覚日から60日以内とされています。ページは「発覚したら、まずは速やかに報告してください」としています。なお、事業所管大臣に権限が委任されている業種では、報告先が個人情報保護委員会ではなく委任先の府省庁になる点にも注意してください。

SaaS の開発チームが事前に決めておくべきことは次のとおりです。

- 漏えいの疑いを判断する責任者と、その代理
- 顧客企業の窓口と連絡手段。B2B SaaS では、顧客企業自身が報告義務を負う立場になり得るため、顧客への速やかな連絡が特に重要になる
- 第5章のログから「いつから、誰の、どのデータが」を調べる手順
- 外部の専門家（セキュリティ・法務）の連絡先

速報の期限が数日であることを考えると、事故が起きてから体制を考えていては間に合いません。

---

## 前日と1週間前にやること

1週間前には時間のかかる確認と変更を終え、前日は「変わっていないこと」を確かめるだけにするのが安全です。

| 時期 | やること | 対応する章 |
|---|---|---|
| 1週間前 | 2テナント×2アカウントで、IDの直接指定・権限外API・エクスポートの越境を試す | 1 |
| 1週間前 | ログアウト後・アカウント停止後に、古いトークンで操作できないことを確かめる | 2 |
| 1週間前 | 開発中に触れた鍵をすべて本番用の新しい値に入れ替え、古い鍵を無効化する | 3 |
| 1週間前 | 別環境へのバックアップ復元を通しで試し、かかった時間と戻らなかったものを記録する | 4 |
| 1週間前 | ログとエラー監視に、入力値・トークン・決済情報が出ていないかを確かめる | 5 |
| 1週間前 | 依存関係の監査を回し、重大な既知脆弱性を解消する | 10 |
| 1週間前 | インシデントの責任者・顧客窓口・外部専門家の連絡先を文書にする | 12 |
| 前日 | 本番の管理者アカウントを棚卸しし、テスト用アカウントとシードデータの管理者を無効化する | 9 |
| 前日 | ストレージの公開設定と、署名URLの有効期限を確認する | 7 |
| 前日 | 決済をライブモードに切り替えた後、Webhookの署名検証と二重処理の防止が本番の設定で動くことを確かめる | 8 |
| 前日 | レート制限と、従量課金サービスの予算アラートが本番で有効になっていることを確かめる | 11 |
| 前日 | 最新のバックアップが取れていること、復元手順の文書がすぐ開ける場所にあることを確かめる | 4 |

---

## 自分たちで確認するか、第三者に頼むか

この記事の項目の多くは、社内で確認できます。判断が分かれるのは、**テナント分離を含む認可の正しさ、決済、個人データの扱い**の3領域です。ここは業務ルールに照らして「この人がこのデータを見てよいか」を一つずつ判断する作業で、ツールの結果だけでは確定しません。また、作った本人は自分が想定した使い方でしか試さない傾向があります。

第三者に頼む場合も、この記事のチェックリストを先に回しておけば、診断の時間を設計判断が必要な部分に集中させられます。実データを入れる前の第三者の確認は、[Webアプリのセキュリティ監査](/security-audit)でお受けしています。見る範囲と見ない範囲、各プランの内容はそのページにまとめています。診断の結果がどのような形で届くかは、[公開前ライト診断のサンプルレポート](/vibe-coding/sample-report)で確認できます（架空のアプリを題材にした見本です）。

創業者がエンジニアではなく、まず自社のアプリがどの程度危ないかを知りたい場合は、コードを読まずに答えられる[無料の20問セルフチェック](/vibe-coding/checkup)から始めるのが手軽です。

---

## まとめ

- 実データを入れる前に確かめるのは、「他社・他人のデータが見えない」「壊れても戻せる」「漏れたら気づいて報告できる」の3つ。
- 最優先はテナント分離。2テナント×2アカウントで、IDの直接指定がすべて拒否されることを確かめる。
- 開発中に触れた鍵はすべてローテーションし、バックアップは別環境への復元で確認する。バックアップへのアクセス権も本番DBと同じ重さで絞る。
- ログは調査に足りる情報を残しつつ、機微情報を出さない。削除はバックアップやログまで含めて設計する。
- 漏えい等が一定の要件に当たると個人情報保護委員会への報告が義務になり、速報は発覚から3〜5日以内。連絡体制は事故の前に決めておく。

どの項目も、実データが入った後に見つかると対応コストが跳ね上がります。逆に言えば、今のうちに一度通しておくだけで、最初の顧客を安心して迎えられる状態に近づけます。
