診断レポート(見本)
- 題材
- 小さな教室やサロン向けの予約サービス(架空)。AIのコーディングツールで作られ、データベースとログインに Supabase、回数券のカード決済に Stripe を使っている、という設定です。まだ公開前です。
- 判定のしかた
- エンジニアがコードを読んで判定する、手動レビューの書き方で示しています。ツールが自動で出した結果ではありません。
見本:架空のアプリ(AIで作った予約サービス)を題材にした、フォーマットの見本です。実在の顧客・実際の診断結果ではありません。
納品物 1致命的な穴(RLS 未設定・秘密情報の露出・所有者チェック欠落・決済の二重処理)の有無判定
判定:どの観点にも、塞ぐべき穴が見つかりました
観点ごとに、穴があるかないかを判定します。この診断が見るのは公開してはいけない致命的な穴だけなので、見つかった穴の重大度はどれも「致命的」です。直す順番は、このアプリで実際に何が起きうるかで決めています。
| 観点 | 判定 |
|---|---|
| データベースの閲覧制限(RLS) | 穴あり重大度 致命的優先度 2 |
| 秘密情報の露出 | 穴あり重大度 致命的優先度 1 |
| 所有者チェック | 穴あり重大度 致命的優先度 3 |
| 決済の二重処理 | 穴あり重大度 致命的優先度 4 |
見本なので、書き方が分かるよう、すべての観点に所見を入れています。実際の診断では、穴が見つからない観点は「見つからなかった」と判定します。
見本:架空のアプリ(AIで作った予約サービス)を題材にした、フォーマットの見本です。実在の顧客・実際の診断結果ではありません。
納品物 2非エンジニア向けレポート(専門用語には言い換えを添えた A4 数枚)
所見:何が起きていて、事業にどう響くか
専門用語には、その場で言い換えを添えています。直す順番(優先度)の高いものから並べています。
優先度 1重大度 致命的手動レビュー秘密情報の露出
決済の秘密鍵が、ブラウザに届くコードに入っている
- 見つかったこと
- 決済サービス(Stripe)の秘密鍵が、利用者のブラウザに配信されるコードの中に書かれていました。秘密鍵は、本来サーバーだけが持つべき「お店の金庫の鍵」です。ページを開いた人なら誰でも、ブラウザの開発者ツールで読めてしまいます。
- 事業への影響
- 鍵を手に入れた人は、あなたのアカウントとして、返金を出す、顧客の情報を読み出す、といった操作ができます。お金に直接つながり、気づいたときには操作が済んでいる種類の穴です。
- 直し方
- まず Stripe の管理画面で新しい鍵を作り、古い鍵を使えない状態にします。この作業はAIに任せず、ご自身で行ってください。漏れた鍵は取り替えるまで使えるままなので、いちばん先に対応します。そのうえで、新しい鍵はサーバー側の処理からだけ使うように直します。
- 大丈夫だった点
- 画面側に入っている Supabase の公開用の鍵は、もともとブラウザに渡す前提の鍵なので問題ありません。データを守るのは、次の項目のデータベース側の設定の役目です。
優先度 2重大度 致命的手動レビューデータベースの閲覧制限(RLS)
予約の情報を、ログインしていない人でも全件読める
- 見つかったこと
- 予約を保存している表に、RLS(誰がどの行を見てよいかを決める、データベース側の設定)がありませんでした。そのため、ページに入っている公開用の鍵を使えば、ログインしていない人でも、全利用者の予約(名前・電話番号・日時)を読み出せます。
- 事業への影響
- お客様の個人情報が、外から一覧で取れる状態です。漏えいが起きれば、利用者への連絡などの対応に追われ、サービスの信用を大きく損ないます。
- 直し方
- 予約の表で RLS を有効にし、「ログインしている本人の予約だけを読める・変えられる」というルールを足します。お店側が全件を見る管理画面が要るなら、それは管理者の権限として別に許可します。
- 大丈夫だった点
- メニューや営業時間の表は誰でも読める設定でしたが、もともと公開する情報なので問題ありません。「誰でも読める」こと自体ではなく、読まれて困る情報かどうかで判断しています。
優先度 3重大度 致命的手動レビュー所有者チェック
予約番号を書き換えると、他人の予約を取り消せる
- 見つかったこと
- 予約を取り消す処理が、画面から送られてきた予約番号だけを見て動いていました。その予約が、いまログインしている本人のものかを、サーバー側で確かめていません。画面には自分の予約しか出ませんが、送る番号を変えれば他人の予約にも届きます。
- 事業への影響
- ログインできる人なら誰でも、番号を変えて送るだけで、他人の予約を取り消せます。いたずらで空いた枠はお店の売上を減らし、お客様は理由の分からない取り消しに困ります。
- 直し方
- 予約を取り消す・変える処理の最初で、「この予約の持ち主は、いまログインしている人か」を確かめ、違えば断ります。画面に出さないだけでは、守りになりません。なお、この処理はデータベースの制限を飛び越えられる強い鍵で動いているため、前の項目の RLS を直しても、この穴は残ります。
- 大丈夫だった点
- 新しく予約を作る処理は、ログイン中の本人の情報をサーバー側で付けていたので問題ありません。
優先度 4重大度 致命的手動レビュー決済の二重処理
同じ支払い完了の通知が2回届くと、回数券が2回分付く
- 見つかったこと
- 回数券を買うと、Stripe から「支払い完了」の通知が届き、アプリが残り回数を足します。この通知は、通信の状況によって同じものが2回以上届くことがあります。ところがアプリには、すでに処理した通知かどうかを見分ける仕組みがありませんでした。
- 事業への影響
- 同じ通知が2回届くと、1回分の支払いで回数券が2回分付きます。気づかないうちに売上を取りこぼし、あとから回数を直すには、お客様とのやり取りが必要になります。
- 直し方
- 届いた通知の番号(イベントID)を記録しておき、記録済みの番号がもう一度来たら何もしないようにします。このように、同じ処理を2回しても結果が1回分で済む性質を、冪等性(べきとうせい)と呼びます。
- 大丈夫だった点
- 請求する金額は、サーバー側で回数券の種類から決めていたので、画面で金額を書き換えても請求額は変わりません。
見本:架空のアプリ(AIで作った予約サービス)を題材にした、フォーマットの見本です。実在の顧客・実際の診断結果ではありません。
納品物 3そのまま Claude Code / Cursor に貼れる、優先度つきの修正指示
修正指示:優先度の高い順に、AIに貼ってください
1つ貼って直し、アプリが動くことを確かめてから次へ進むと、どの変更で何が変わったかを追えます。
優先度 1決済の秘密鍵が、ブラウザに届くコードに入っている
AIに貼る修正指示の例
このプロジェクトで、ブラウザに配信されるコード(画面側のファイルや、公開用の環境変数)から秘密鍵を使っている箇所を一覧にしてください。鍵の値そのものは表示しないでください。見つかった処理はサーバー側(API ルートなど)に移し、鍵はサーバー専用の環境変数から読むように直してください。
優先度 2予約の情報を、ログインしていない人でも全件読める
AIに貼る修正指示の例
Supabase の予約テーブルで RLS を有効にし、ログイン中のユーザーが自分の予約だけを読み書きできるポリシーを追加してください。変更は新しいマイグレーションとして作り、既存のデータは削除も変更もしないでください。適用する前に、どのテーブルにどんなルールを足すのかを説明してください。
優先度 3予約番号を書き換えると、他人の予約を取り消せる
AIに貼る修正指示の例
予約を取得・変更・取り消しするサーバー側の処理をすべて洗い出し、対象の予約がログイン中のユーザーのものかを、サーバー側で確かめているか1つずつ確認してください。確かめていない処理には所有者のチェックを足し、本人以外からの依頼は断るようにしてください。画面の表示を隠しているだけの箇所は、一覧にして報告してください。
優先度 4同じ支払い完了の通知が2回届くと、回数券が2回分付く
AIに貼る修正指示の例
Stripe の Webhook を受け取る処理を、同じイベントが2回以上届いても二重に処理しないように直してください。処理したイベントIDを重複しない値として保存し、保存済みのIDが届いたら何もせずに成功を返してください。既存の購入データや残り回数は変更しないでください。
指示文に、鍵やパスワードの値を書き足さないでください。AIに伝えるのは、どこをどう直すかだけで足ります。
見本:架空のアプリ(AIで作った予約サービス)を題材にした、フォーマットの見本です。実在の顧客・実際の診断結果ではありません。
納品物 430分の説明通話(何が危なくて、何が大丈夫かを口頭で)
説明通話:この見本なら、こう話します
何が危なくて、何が大丈夫かを、口頭でお伝えします。この見本の場合は、次の順に話します。
- 優先度の高い項目から順に、放っておくと何が起きるのか
- 残りの項目を、公開までにどの順で直すか
- 大丈夫だった点:心配しなくてよいこと