最初に結論から述べます。セキュリティ対策には、ライブラリやツールで自動的に潰せる「水平の統制」と、人手の監査でしか塞げない「垂直のリスク」があります。 この2つを区別できるかどうかが、限られた予算で安全に出荷できるかの分かれ目です。
- 水平の統制=セキュリティヘッダー/CSP、レート制限、CSRF、入力検証、既知の脆弱な依存、秘密情報の混入。アプリをまたいで一律に効くので、無料のツールで機械的に潰せます。
- 垂直のリスク=認可(IDOR/BOLA)、Supabase RLSの設計妥当性、テナント分離、業務ロジック(数量・価格・状態遷移の悪用)。「誰が何を所有し、どの操作を許されるか」というあなたの事業固有のルールに依存するので、機械には正しさを判定できません。
費用対効果が最も高いのは、この順番です。まず無料ツールで水平統制を一掃し、機械には判定できない垂直リスクだけを監査に回す。 全部を人手でやればコストが膨らみ、全部をツールに任せれば最も深刻なリスク(認可)が素通りします。本記事は、その境界線——「セキュリティ監査」で実際に何を見るのか、自動化でどこまで足りてどこから足りないのか、いつ監査が要るのか、どう進めていくらかかるのか——を、できる限り正直に解説します。
先に一番大事なことを断っておきます。監査は「完全に安全」を約束しません。 それを約束する人や製品がいたら、むしろ信用しないでください。「入れたから/受けたから大丈夫」という油断こそが、最悪のセキュリティ結果を生みます。監査ができるのは、既知の重大リスクを体系的に潰し、回帰を防ぐ仕組みを残し、残るリスクを正直に明示するところまでです。
1. セキュリティ対策は「水平」と「垂直」に分かれる
なぜこの2分法が効くのか。「ライブラリが正しく所有できる対策かどうか」で、最適な道具が変わるからです。
| 水平の統制(自動化できる) | 垂直のリスク(監査が要る) | |
|---|---|---|
| 例 | ヘッダー/CSP、レート制限、CSRF、入力検証、脆弱な依存、秘密混入 | 認可(IDOR/BOLA)、RLS設計、テナント分離、業務ロジック、権限昇格 |
| 性質 | アプリ横断で一律に効く | アプリ固有の「誰が何を所有するか」に依存 |
| 正しさの基準 | 設定・実装の「形」で判定できる | 事業ルールの「意味」を理解しないと判定できない |
| 最適な道具 | 無料のツール/ライブラリ | 人手の設計レビューと検証 |
| ツールにできること | 導入・修正まで | 検出・警告まで(修正は設計判断) |
ここで強調したいのは、「何かを導入すれば認可が守られる」という製品は存在しないということです。水平統制はライブラリで肩代わりできますが、垂直リスクはあなたのデータモデルを知らないツールには塞げません。だからこそ、自動化できるところは徹底的に自動化してコストを下げ、人間は機械にできない判断に集中する——これがいちばん安く、いちばん安全な配分です。
この垂直リスクのうち、最も頻出で最も深刻なのが認可です。オブジェクト単位の認可欠陥(IDOR / BOLA)は、OWASP API Security Top 10で2019年の初版以来ずっと第1位に居座り続けています(OWASP API Security Top 10 (2023) / API1:2023 BOLA)。「めったに起きない高度な攻撃」ではなく、「最も普通に起きる漏洩」です。全体像はNext.js × Supabaseアプリのセキュリティ総合ガイドにまとめていますが、本記事はそのうち「監査とは何か」に絞ります。
「監査」「脆弱性診断」「ペネトレーションテスト」は何が違うか
「セキュリティ監査」という言葉は曖昧に使われがちです。発注の前に、近い言葉との違いを押さえておくと、見積もりや提案の妥当性を判断できます。
| 用語 | 主な問い | やり方 | 向いている場面 |
|---|---|---|---|
| 脆弱性診断(VA) | 既知の脆弱性は残っていないか | ツール中心のスキャン(広く・自動) | 既知の穴を定期的に網羅的に洗う |
| ペネトレーションテスト | 攻撃者は実際に侵入できるか | 攻撃者視点の手動攻撃(深く・狭く・実証重視) | 特定の攻撃シナリオの成否を確かめる |
| セキュリティ監査(本記事) | 設計と実装は「正しく」できているか | 自動検出+設計レビュー+実証+是正設計 | 認可・RLS・テナント分離など設計の妥当性を保証したい |
| コードレビュー | この変更に欠陥はないか | 人手の読み込み(範囲=差分/PR) | 変更単位で日常的に品質を担保する |
本記事の「監査」は、脆弱性診断(自動の網羅)とペネトレーションテスト(実証)の良いところを取り込みつつ、設計レビューに重心を置くのが特徴です。なぜなら、Next.js × Supabaseで最も漏洩を起こすのは「未知の高度な攻撃」ではなく、「認可・RLS設計という、設計段階で決まる垂直リスク」だからです。スキャン結果だけでは、この設計の妥当性は判定できません。
2. 自動ツールが"得意"な範囲(SAST / DAST / SCA / シークレットスキャン)
まず、人手の監査を呼ぶ前に潰しておくべき範囲です。ここは無料・自動で十分に塞げます。お金を払うべきではありません。
| ツール種別 | 何を見るか | 代表的に潰せるもの |
|---|---|---|
| SAST(静的解析) | ソースコードのデータフロー | SQLi・SSRF・パストラバーサル・オープンリダイレクト・DOM XSS |
| DAST(動的解析) | 動いているアプリへの実リクエスト | 反射XSS・オープンリダイレクト・SQLi(真偽/エラー推論)・SSRF |
| SCA(依存スキャン) | package.json / lockfile | 既知の脆弱性を持つnpm依存(CVE)、ライセンス問題 |
| シークレットスキャン | リポジトリ・差分 | ハードコードされた鍵・トークン・接続文字列 |
| ランタイム強化 | ミドルウェア/設定 | セキュリティヘッダー/CSP、レート制限、CSRF/Origin検証、型付きenv境界 |
これらは「アプリ固有の意味」を知らなくても判定できます。SQLインジェクションは、どんなアプリでも「未サニタイズの入力がSQLに連結される」という同じ構造的欠陥だからです。だから、ライブラリやスキャナが正しく所有できます。
私はこの水平統制を、自作のOSS Aegis(MITライセンス)で無料化しています。Next.js × Supabaseに特化したSAST・DAST・シークレットスキャン・ランタイム強化を、インストール不要で実行できます。
# 1) 静的解析(SAST)— いまのプロジェクトのデータフローを追う
npx @aegiskit/cli scan
# 2) ランタイム強化 — ヘッダー/CSP・レート制限・CSRF・型付きenv境界を導入
npx @aegiskit/cli init
# 3) 動的確認(DAST)— 自分のアプリへ安全・非破壊なプローブを送る
npx @aegiskit/cli probe http://localhost:3000 --correlate
補足(正直なスコープ): SCA(依存の脆弱性)は、
npm auditや GitHub の Dependabot/Renovate といったエコシステム標準のツールで十分にカバーできます。わざわざ有料の監査に含める必要はありません。水平統制は「無料ツールの守備範囲」と割り切り、監査の時間は次節以降の垂直リスクに使うのが正解です。
注意:ツールの結果が「クリーン」でも、それは「安全」ではありません。 自動ツールが見ているのは構造的な欠陥の有無であって、あなたの認可やテナント分離が正しいことではありません。スキャンが満点でも、垂直リスクは手つかずのまま残り得ます(この点は第7節で改めて触れます)。だからこそ、自動化は「ゴール」ではなく「監査に入る前の前提条件」と位置づけるのが正しい使い方です。
ここまでの自動化で、世の中の脆弱性の「数」のかなりの割合は機械的に消えます。 ただし——消えないものが残ります。そして残ったものこそが、最も漏洩を起こしているクラスです。
3. 自動ツールが"苦手/不可能"な範囲=監査が要る範囲
ここが本記事の核心です。なぜ機械には垂直リスクを判定できないのか。それが「事業ルールの意味」に依存するからです。
例1:認可(IDOR)は、リクエストとしては完全に正しい
GET /api/invoices/1024 ← 自分の請求書(正規アクセス)
GET /api/invoices/1025 ← IDを1つ増やすだけ。これが他人の請求書を返したらIDOR
/api/invoices/1025 というリクエストは、HTTPとして完全に正常です。認証ヘッダーも正しく、不正な文字列も含まれません。WAFやスキャナから見れば「正規ユーザーの正規リクエスト」です。それが攻撃になるのは、「1025番の請求書がこのユーザーの所有物ではない」という、アプリ固有の業務的事実による——そしてツールはあなたのデータモデルを知りません。IDORがどう生まれ、どう塞ぐかはIDOR/認可欠陥の発見・修正ガイドで詳説しています。
例2:RLS設計の"妥当性"は、ポリシーの有無では決まらない
Supabaseのservice_roleキーは、PostgreSQLのBYPASSRLS属性で動き、RLSを完全に無視します(Supabase: Row Level Security)。つまり「全テーブルにRLSを張った」だけでは安全とは言えません。1本のservice_role経路が所有権チェックを忘れていれば、完璧なRLSも丸ごと飛び越えられます。
ツールは「RLSが未設定」「WITH CHECKがない」「using (true)になっている」といった形の欠陥は検出できます。しかし「このポリシーは、この事業のテナント境界として正しいか?」という設計の妥当性は判定できません。それはあなたの組織モデル(会社 → 部署 → ユーザー、招待、ロール)を理解して初めて判断できるからです。RLSの設定ミス検出はRLS設定ミスの検出・監査ガイド、鍵の取り扱いはanon/service_roleキー露出ガイドを参照してください。
例3:業務ロジックの欠陥は、コードとして"正しい"
これが最も機械に難しい領域です。次のコードを見てください。
// 構文的にもデータフロー的にも完全に正しい。型も通る。
// だが業務ルール上は脆弱。
const total = unitPrice * quantity - couponDiscount;
SASTから見れば、このコードに欠陥はありません。型は正しく、汚染された入力が危険なシンクに流れているわけでもない。しかし——
quantityに 負数を送れたら?totalがマイナス=「買うほど返金される」。couponDiscountを 複数回適用できたら?totalを0以下にできる。- 「下書き」状態の注文を、決済を飛ばして直接「確定」に状態遷移させられたら?
これらは、quantity >= 1、クーポンは1回だけ、確定の前に必ず決済という業務ルールを知っている人間にしか「悪用」だと分かりません。機械にとっては、すべて妥当な数値・妥当な状態遷移です。これがマルチテナントSaaSになると、「他テナントのIDを混ぜて操作する」テナント越境と組み合わさり、被害が一気に広がります(マルチテナントのテナント越境リーク検証)。
特に状態遷移は見落とされがちです。次のAPIは、認証も型も完璧で、所有権チェックまで正しく書かれています。
// 注文の状態を更新するAPI。認証済み・型安全・所有権チェックあり。
// だが状態機械のルールを検証していない。
await supabase
.from("orders")
.update({ status: nextStatus }) // ← "paid" を直接渡せてしまう
.eq("id", orderId)
.eq("user_id", user.id); // 所有権は正しく縛っている
user_id で所有権を縛っているのに、「draft → paid の間に必ず決済を通す」という状態機械のルールが抜けています。攻撃者は status に直接 "paid" を送り、決済を飛ばして注文を確定できる。SASTもRLSも、この欠陥を「悪用」とは判定できません。型として正しく、所有者本人の操作で、許可されたカラムの更新だからです。「この遷移はビジネス上許されるのか」を知っているのは、ドメインを理解した人間だけです。
そしてもう一つの現実があります。AIで量産したコードでは、こうした垂直リスクが特に作り込まれやすい。Veracodeが100以上のLLMに4言語80タスクを課した2025年の調査では、AI生成コードの45%が既知のセキュリティ欠陥を含み、モデルが賢くなってもセキュリティ成績は横ばいでした(Veracode 2025 GenAI Code Security Report)。AIは「デモで動くコード」を最短で書きますが、「他人のデータを見せない」「負数を弾く」はハッピーパスの外側にあり、デモでは絶対に顕在化しないからです。
実際の重大インシデントもあります。2025年登録のCVE-2025-48757は、AIビルダー製サイトの不十分なRLSにより未認証の攻撃者が任意テーブルを読み書きできた事例で、分類はCWE-863(Incorrect Authorization)、CVSS基本値9.3 CRITICALです。認可はプラットフォームが肩代わりしてくれない、あなたの責任範囲だと、このCVEは雄弁に物語っています。
無料の「検出」と、監査の「修正」はどこで分かれるか
ここまでを一枚にまとめると、こうなります。無料OSSは検出・警告まで、有料の監査は設計・実装で実際に塞ぐ。 同じリスクでも、やることが違います。
| リスクの次元 | 無料OSS(Aegis)がやること | 有料の監査がやること |
|---|---|---|
| 認可 / IDOR・BOLA | 所有権スコープのない汚染入力を静的解析で検出・警告 | 認可モデルを設計し直し、所有権チェックを実装して塞ぐ |
| Supabase RLS | 未設定・WITH CHECK欠落・USING(true)・service_role経路を検出 | 正しいRLSポリシーを設計・実装し、越境しないことを検証 |
| テナント分離 | 弱いRLSのテーブルへの非管理アクセスを「確定した露出」として相関 | テナント境界を再設計し、分離が壊れていないことを証明 |
| 業務ロジック | 対象外(数量・価格・状態遷移はライブラリに判定できない) | ドメインを理解した人手のレビューで悪用経路を洗い出す |
| 水平統制(ヘッダー/レート制限ほか) | ミドルウェア1枚で自動導入し、CIで逸脱を検出 | 導入状況を検証し、抜け・誤設定を塞ぐ(自動化の裏取り) |
「検出」と「修正」は別の仕事です。検出だけ無料で済ませ、修正の設計判断が必要なところだけ監査に回す——この切り分けが、コストを最小化します。
4. 監査が実際に見る項目(チェックリスト)
では、人手の監査は具体的に何を見るのか。「何となく全部見る」ではなく、観点を構造化して、漏れなく潰します。良い監査は、所見を OWASP ASVS のような認知された検証標準にマップして、「個人の意見」ではなく「再現可能な根拠」として提示します(OWASP ASVS)。
4-1. 認可モデル / IDOR・BOLA
| 見る項目 | 何を確かめるか | 危険信号 |
|---|---|---|
| 所有権の強制 | クライアントが操作できるID(route params・body・query)が、所有権で絞られてDBに届くか | .eq("id", id) だけで返している(user_idもRLSも無い) |
| 認可の一元化 | 認可がDB(RLS)かサーバーの1か所に集約され、ルート追加で書き忘れない構造か | ルートごとに所有権チェックを手書きしている |
| Server Actions | "use server" の引数・formData も「クライアント操作可能」として扱っているか | 「画面に出していないIDだから安全」という思い込み |
4-2. Supabase RLSポリシー
| 見る項目 | 何を確かめるか | 危険信号 |
|---|---|---|
| 有効化 | 全テーブルでRLSが有効か(fail-secure) | enable row level security のないテーブル |
書き込みのWITH CHECK | INSERT/UPDATEで挿入後の行が条件を満たすか検証しているか | using だけで with check がない |
| 無条件許可 | using (true) のような実質ノーガードのポリシーがないか | using (true) / anon への過剰付与 |
| 関数の権限昇格 | SECURITY DEFINER 関数が search_path を固定しているか | 固定なしの definer 関数(権限昇格の温床) |
| 性能 | auth.uid() を (select auth.uid()) で包んでいるか | 大きなテーブルで行ごとに再評価=遅い |
4-3. service_role経路
| 見る項目 | 何を確かめるか | 危険信号 |
|---|---|---|
| 鍵の所在 | service_role キーがブラウザ/クライアントに漏れていないか | フロントのコードやネットワークタブに鍵が見える |
| 所有権の強制 | service_role を使うAPIで user_id 等の所有権条件を必ず付けているか | RLSを越えたまま .eq("id", ...) だけ |
| 経路の最小化 | service_role を使う経路が本当に必要な箇所だけに限定されているか | 「悩むより管理者クライアント」で多用 |
4-4. テナント境界(マルチテナント)
| 見る項目 | 何を確かめるか | 危険信号 |
|---|---|---|
| 分離の単位 | テナントの境界(会社/組織ID)が全クエリ・全ポリシーで一貫して効くか | テーブルによって分離キーがバラバラ |
| 越境テスト | テナントAのセッションでテナントBのIDを叩いて弾かれるか | 別テナントのデータが200で返る |
| 集計・結合 | JOINや集計、RPC、Storageでテナント境界が漏れていないか | 「主要テーブルは大丈夫」で結合先を見ていない |
4-5. 入力境界・業務ロジック・再発防止
| 見る項目 | 何を確かめるか | 危険信号 |
|---|---|---|
| 入力境界 | SQLi・SSRF・XSS・オープンリダイレクト等が境界で検証されるか | 境界バリデーション(Zod等)がない |
| 業務ロジック | 数量・価格・割引・状態遷移の悪用経路を、ドメインを理解して洗い出したか | 「正常系しかテストがない」 |
| 回帰防止 | RLSの回帰テスト(pgTAP)とCIゲートが残っているか | 「手元で動いた」以外の根拠がない |
監査では、これらをAegisの静的解析(SAST)・RLS検証・動的確認(DAST)の相関を土台にしつつ、最後は人手のレビューで実害を確定します。ツールが「疑い」を出し、人間が「事業ルールに照らして本当に悪用できるか」を判断する——この役割分担が、ノイズを増やさずに深く見るコツです。
監査が踏み込む「設計の妥当性」——RLSの例
ツールは「RLSがある/ない」を見ます。監査は「そのRLSが、この事業のテナント境界として正しいか」を見ます。例えば次のポリシーは、ツール的には合格です——RLSは有効で、using も with check もあります。
-- 一見正しい。だが「ユーザー個人」単位でしか縛れていない。
create policy "members manage documents"
on documents for all
to authenticated
using ( (select auth.uid()) = user_id )
with check ( (select auth.uid()) = user_id );
しかし、これがB2BのマルチテナントSaaSなら欠陥です。境界は「ユーザー個人」ではなく「所属する組織(テナント)」であるべきだからです。このままだと、チームで共有すべき文書を作成者本人しか触れず、組織への招待・退会のフローでも権限が破綻します。監査はこれを「組織境界」に設計し直します。
-- 監査後:テナント(組織)を境界にし、所属を介して認可する。
create policy "org members manage documents"
on documents for all
to authenticated
using (
org_id in (select org_id from memberships where user_id = (select auth.uid()))
)
with check (
org_id in (select org_id from memberships where user_id = (select auth.uid()))
);
この「正しく動くが、事業ルールとしては間違っている」を見抜くのが、ツールにはできず監査にできることです。検出(形)と妥当性(意味)の差が、ここに表れます。
所見はこう書かれる(サンプル)
監査の成果物は「危ないと思います」という感想ではありません。開発チームがその場で着手できるよう、再現可能な根拠として、最低でも次の要素を備えた所見の集合になります。
[CRITICAL] authz/idor — 他テナントの請求書を取得可能
場所: app/api/invoices/[id]/route.ts:18
経路: params.id (source) → supabaseAdmin.from("invoices").eq("id", id) (sink)
原因: service_role 経路で所有権条件 (user_id / tenant_id) が欠落
再現: ユーザーAのセッションで GET /api/invoices/<Bの請求書ID> → 200 で返却
影響: 全テナントの請求データの閲覧(CWE-863 / OWASP API1:2023 BOLA)
是正: 案A=RLSに認可を寄せる / 案B=service_role経路に .eq("tenant_id") を強制
検証: pgTAP で「他テナントの行が0件」を回帰テスト化し CI ゲートに追加
重大度(CRITICAL/HIGH/…)、source→sinkのトレース、実際に再現した手順、影響範囲、是正方針、そして回帰テストの形まで揃って初めて、所見は「直せる成果物」になります。「指摘して終わり」ではなく「直せる形で渡す」——ここが監査の品質を分けます。
5. 監査が必要になるタイミング
「全員が今すぐ監査を受けるべき」とは言いません。費用対効果で考えると、監査が要るのは次のような局面です。
- エンタープライズ案件 / RFP対応: 大企業との取引では、セキュリティ質問票やRFPで「第三者の診断結果」を求められます。
service_roleの扱いやテナント分離を文書で示せるかが受注条件になります。 - コンプライアンス要求(SOC2 / ISO 27001 など): 認証取得の過程で、アプリケーションレベルの脆弱性診断が要件に含まれます。
- 資金調達のデューデリジェンス(DD): 投資家のテクニカルDDで、認可・データ分離・依存の健全性が問われます。「漏洩しうる設計」は評価額に直結します。
- インシデントの後: 一度漏らした後は、同じクラスの欠陥が他にも潜んでいる可能性が高い。再発防止の仕組みごと入れ直す必要があります。
- AIで大量生成した直後のリリース前: これが今いちばん多いケースです。第3節のとおり、AI生成コードは垂直リスクを作り込みやすい。速く作れたものを、漏らさず出すための最後の関門として効きます。
逆に、まだ水平統制すら自動化していない段階なら、監査より先に無料ツールを回すべきです。順番を間違えると、無料で潰せたはずのものに監査費用を払うことになります。
同じ理由で、急いで監査を受けなくてよいケースもあります。社外に出していない検証用プロトタイプ、まだユーザーデータを持たないMVP、対外的な要求がまだない段階——ここでまず必要なのは、無料の自動化と、第8節の最小限の垂直チェックです。監査は「守るべきデータ」と「それを問う相手」が現れたときに、最大の費用対効果を発揮します。
参考:RFP・セキュリティ質問票でよく問われること
エンタープライズ取引で実際に問われ、監査の所見がそのまま回答根拠になる項目の例です。
- データはテナント単位で論理的に分離されているか(その仕組みと検証方法)
- 認可(オブジェクト単位のアクセス制御)をどう強制しているか
- 第三者による脆弱性診断/監査の実施有無と、直近の結果
- 依存ライブラリの脆弱性管理(SCA)とパッチ運用
- 秘密情報の管理(環境変数・鍵のローテーション・混入防止)
- インシデント対応の手順と、ログ・監査証跡の保全
これらに「文書で」答えられるかが受注の分かれ目になります。監査は、この回答の裏付けを作る作業でもあります。
6. 進め方(3段階)と費用感
監査は「受けるか/受けないか」の0/1ではありません。得たいものに応じて深さを選べる3段の梯子にしています。料金はセキュリティ監査ページに明記していますが、要点はこうです。
| 段階 | 価格(税別) | 期間 | 何が得られるか | 修正実装 |
|---|---|---|---|---|
| スポット診断 | ¥98,000〜 | 約1週間 | 優先度つきの所見レポート(source→sinkトレース/該当SQL付き)。「今どれだけ穴があるか」を正確に可視化 | 含まない |
| 標準監査(推奨) | ¥280,000〜 | 約2〜3週間 | 認可モデル・RLS・service_role経路・テナント境界の設計レビュー+脅威モデル+修正設計プラン+報告会 | 設計まで |
| 伴走・修正実装 | ¥680,000〜 | 数週間〜 | 修正の実装(RLS再設計・所有権チェック・テナント分離)+回帰テスト/CIゲート常設+再監査で「直った」を証明 | 含む |
各段階の使い分けは明確です。
- スポット診断は「健康診断」。まず現在地を正確に知りたいときに。修正は含まないので、社内に手があるチーム向けです。
- 標準監査は「設計まで踏み込む本格監査」。B2B・マルチテナントSaaSを安全に出荷/運用したいときの標準形で、修正の設計プランまで提供します。
- 伴走・修正実装は「検出で終わらせず、実際に塞いで再発しない状態まで」。一人 × 生成AI(Claude Code)で、設計から実装・テストまで速く進めます。
価格はすべて**「から」の正直な目安(税別)です。固定見積もりでも上限でもありません。対象アプリの規模(テーブル数・エンドポイント数・要件)で変動するため、まず無料相談でスコープをすり合わせてから見積もりします。本番データや守秘が絡む場合はNDAに対応し、動的確認(DAST)はあなたが所有する環境に対して、localhost既定・スコープ固定・リクエスト予算つきの非破壊なプローブのみ**を行います(破壊的操作は実施しません)。
なお、対象は最も深く・速く・安全に踏み込める Next.js(App Router)× Supabase を主としています。考え方(認可・入力検証・多層防御)は汎用ですが、それ以外の構成は無料相談で範囲を確認させてください。
監査の実際の流れ(5ステップ)
スポット/標準のどちらでも、おおまかな流れは共通です。
- 無料相談・スコープ確定: 対象リポジトリ・エンドポイント・テナントモデル・利用中のSupabase機能(RLS/RPC/Storage/Edge Functions)を確認し、見積もりと範囲を文書化します。
- 自動検出: Aegisの静的解析(SAST)・
supabase/migrationsのRLS検証・動的確認(DAST)を回し、機械で拾える穴を一掃します。ここは無料ツールの範囲で、所見の「土台」になります。 - 手動レビュー(標準監査の主役): 認可モデル・RLSポリシー・
service_role経路・テナント境界・業務ロジックを、ドメインを理解したうえで読み込みます。自動の「疑い」を、事業ルールに照らして「実害」へ確定させます。 - 報告(報告会つき): 重大度・再現手順・是正方針つきの所見レポートを提出し、オンラインで質疑と優先順位をすり合わせます。
- 是正と再監査(伴走プラン): 修正を実装し、回帰テストとCIゲートを常設し、再監査で「直った」ことを証明します。
良い監査を見分けるための質問
最後に、これは自分の宣伝に不利になっても書いておきます。発注する側が、相手の質を見抜くための質問です。
- 「残るリスクはどう報告されますか?」——「完全に安全になります」と即答する相手は避けてください。誠実な監査は、範囲外と残リスクを必ず明示します。
- 「再発防止に何を残しますか?」——回帰テストやCIゲートの話が出ないなら、その場限りで終わる監査かもしれません。
- 「
service_role経路とテナント越境はどう検証しますか?」——具体的な手順(2アカウント/2テナントでのID差し替え等)を語れるかで、垂直リスクへの理解が分かります。 - 「所見はどんな形で渡されますか?」——source→sinkのトレースと再現手順、是正方針まで揃うのが望ましい形です。
これらに具体的に答えられる相手なら、垂直リスクを本当に理解しています。逆に「ツールに任せれば大丈夫」しか言わないなら、最も漏洩を起こすクラスが素通りする可能性が高いと考えてください。
7. 監査の正直な限界
ここは、このページで一番大事な節です。きれいごとを書きません。
監査は「完全に安全」「絶対に漏れない」を約束しません。 そう約束する相手は信用しないでください。セキュリティは一度きりの作業ではなく、継続的な営みです。監査が誠実に提供できるのは、次の3つだけです。
- 既知の重大リスクを体系的に潰す。 第4節のチェックリストに沿って、最頻出かつ最も深刻なクラス(認可・RLS・テナント分離・業務ロジック)を漏れなく洗い、優先度をつけて塞ぎます。
- 回帰を防ぐ仕組みを残す。 監査の本当の価値は「その時点で直す」ことではなく、二度と同じ穴を開けない構造を残すことです。RLSの回帰テスト(pgTAP)とCIゲート(高信頼の検出だけがビルドを止め、SARIFをGitHubに残す)を常設し、監査後に書かれる新しいコードにも歯止めをかけます。
- 残るリスクを明示する。 監査範囲(対象リポジトリ・エンドポイント・期間)を文書化し、範囲外のものは「見ていない」と正直に書きます。「クリーンな結果」は「よくある罠は踏んでいない」であって、「安全が証明された」ではありません。
監査のスコープは、最初に文書で固定します。何を含み、何を含まないかを曖昧にしないことが、誠実さの第一歩です。
| 監査に含まれるもの(例) | 監査に含まれないもの(例) |
|---|---|
| アプリの認可・RLS・テナント分離・入力境界・業務ロジック | 物理/オフィスのセキュリティ、人的な内部不正 |
| Supabase(RLS/RPC/Storage)の設計と実装 | Supabase基盤そのものの脆弱性(ベンダー責任範囲) |
| 対象リポジトリ・エンドポイントの静的/動的検証 | 範囲外のサブシステム・外部SaaS連携先の内部 |
| 監査時点のコードベース | 監査後に追加・変更されたコード(→CIゲートで担保) |
特に誤解されやすいのが、監査はスナップショットだという点です。監査が終わった翌日に書いたコードは、監査の対象外です。だからこそ②のCIゲートが本質で、「一回診てもらって終わり」では片手落ちになります。
そしてツールの限界も同じです。いかなる静的・動的ツールも、あなたの認可が正しいことを証明はできません。ツールが見ているのは実装の「形」であって、事業ルールの「意味」ではない。この3層(SAST・RLS検証・DAST)と人手のレビューは、脅威モデリングを補完するもので、置き換えるものではありません。それでも、最頻出の穴を機械的に潰し、人間が本当に難しい判断に集中できる価値は計り知れません。
8. まず、自分でできること
監査を呼ぶ前に——あるいは呼ぶかどうかを決める前に——無料でできることを先にやってください。 それが一番コスト効率が良く、監査を受けるとしても所見がシャープになります。
- 水平統制を無料ツールで一掃する。 まずは現状把握から。
npx @aegiskit/cli scan # SAST: いまの穴を可視化 npx @aegiskit/cli init # ランタイム強化を導入 npx @aegiskit/cli probe http://localhost:3000 --correlate # DASTで裏取り npm audit/ Dependabot で依存(SCA)を潰す。 既知の脆弱な依存はここで消えます。- 最小限の垂直チェックを自分でやる。 全テーブルにRLS、
service_role経路の所有権チェック、そして2アカウントでのID差し替えテスト1本。この3点だけでも、CVE-2025-48757クラスの事故の大半は防げます。
ここまでやってなお残るのが、機械には判定できない垂直リスク——認可モデルの妥当性、RLS設計、テナント境界、業務ロジック。そこに不安があるなら、それが監査の出番です。無料ツールの詳細はAegis(OSS)のページ、監査の範囲と料金はセキュリティ監査ページにまとめています。
よくある質問(FAQ)
Q. 無料のOSSがあるのに、なぜ有料の監査が必要なのですか? A. 別の仕事だからです。OSS(Aegis)は、ライブラリが正しく所有できる水平統制を自動化し、ライブラリに直せない垂直リスクは検出・警告までを担います。その垂直リスクを実際に塞ぐのは設計判断と実装であり、そこが監査の役割です。検出(無料)と修正(監査)を混同しないことが、無駄な出費を避けるコツです。
Q. 自動ツールのスコアが満点なら、もう安全ですか? A. いいえ。第7節のとおり、クリーンな結果は「よくある罠は踏んでいない」であって「安全が証明された」ではありません。認可・テナント分離・業務ロジックは、ツールが構造的に判定できない領域です。満点は出発点であって、ゴールではありません。
Q. スポット診断と標準監査、どちらを選べばいいですか? A. 社内に修正できる手があり「現在地の正確な把握」が欲しいならスポット診断(約1週間・¥98,000〜)。B2B/マルチテナントを安全に出荷したい、設計まで踏み込んでほしいなら標準監査(約2〜3週間・¥280,000〜)です。迷う場合は無料相談で対象を見てから提案します。
Q. 監査を受ければ「完全に安全」になりますか? A. なりません。そう約束するものは信用しないでください。監査は既知の重大リスクを体系的に潰し、回帰を防ぐ仕組み(テスト・CIゲート)を残します。しかし「完全」「絶対」はなく、残るリスクは明示します。これは弱気ではなく、セキュリティを誠実に扱う前提です。
Q. 本番データを渡すのが不安です。 A. NDAに対応します。動的確認(DAST)はあなたが所有する環境に対して、localhost既定・スコープ固定・リクエスト予算つきの非破壊なプローブのみを行い、破壊的操作はしません。秘密情報は受け取らない設計を基本とし、必要な権限は最小限に限定します。
Q. 監査はどのくらいの頻度で受けるべきですか? A. 一律の正解はありませんが、目安は「大きな設計変更のたび」と「年1回程度の定期」です。ただし頻度そのものより重要なのは、回帰を防ぐCIゲートを常設し、日々の変更を自動で見張る状態にしておくこと。監査は節目の深い点検、CIは毎日の見張り——役割が違います。
Q. AIに「セキュアに書いて」と頼めば、監査は不要になりますか? A. 期待しすぎないでください。Veracodeの調査では、モデルが賢くなってもセキュリティ成績は横ばいでした。AIは「動くコード」の生成には強いが、「壊れない構造」は保証しません。AIの速さを活かしつつ、検証ゲート(スキャン・テスト・レビュー)を通して初めて本番品質になります。
Q. 個人開発や小規模でも監査は要りますか? A. まずは第8節の無料の3点を必ずやってください。それで十分なことも多いです。監査が要るのは、エンタープライズ取引・コンプライアンス・資金調達DD・インシデント後・AI大量生成後のリリース前など、「第三者の根拠」や「設計の妥当性の保証」が必要になったときです。
まとめ:自動化で潰し、監査で塞ぎ、CIで再発を止める
要点を整理します。
- セキュリティ対策は**「自動化できる水平統制」と「監査が要る垂直リスク」**に分かれる。費用対効果が最も高いのは、まず無料ツールで水平を潰し、機械に判定できない垂直リスクだけを監査に回す順番です。
- 自動ツール(SAST/DAST/SCA/シークレットスキャン)が得意なのは注入・ヘッダー/CSP・レート制限・脆弱な依存・秘密混入。無料OSS(
npx @aegiskit/cli scan)で機械的に潰せます。 - 監査でしか塞げないのは認可/IDOR・RLS設計の妥当性・テナント分離・業務ロジック。機械に判定できないのは、それが**事業ルールの「意味」**に依存するからです。
- 監査が見るのは、認可モデル・RLSポリシー・
service_role経路・テナント境界・入力境界・業務ロジック・再発防止——構造化したチェックリストを、ASVSのような標準にマップして潰します。 - 正直に言うと、監査は「完全に安全」にはしません。 できるのは、既知の重大リスクを体系的に潰し、回帰を防ぐCIゲートを残し、残るリスクを明示すること。「絶対安全」を約束する相手は信用しないでください。
AIで速く作ること自体は正しい。速く作ったものを、漏らさず安全に固める——その境界線を、無料の自動化と人手の監査でどう引くか、本記事がその判断材料になれば幸いです。まずはAegis(無料OSS)で現在地を可視化し、垂直リスクに不安が残るならセキュリティ監査でご相談ください。マルチテナントB2B SaaSを安全に運用してきた具体例は木材流通DXの事例にまとめています。
参考資料
- OWASP API Security Top 10 (2023)
- OWASP API1:2023 — Broken Object Level Authorization (BOLA)
- OWASP Application Security Verification Standard (ASVS)
- Veracode — 2025 GenAI Code Security Report(AI生成コードの45%にセキュリティ欠陥)
- Supabase Docs — Row Level Security(service_roleはRLSをバイパスする)
- NVD — CVE-2025-48757(不十分なRLSによる未認証アクセス、CWE-863、CVSS 9.3 CRITICAL)