Vibe Codingセキュリティレビュー — 本番前にテストすべき項目

Vibe Coding Rescue · 2026-07-22 · データとセキュリティ
最終確認 2026-07-23対象 Next.js · Supabase · Stripe公式資料 14件

ログインとテスト決済が成功すると公開準備が整ったように見えますが、セキュリティ上の不具合は、本来拒否されるべきリクエストを試すと見つかりやすいものです。以下は専門家によるセキュリティ評価の代わりではなく、本番公開前に行う実務的な確認項目です。

ステージング環境でのみテストを実行してください。自分が所有しているか、明示的にテスト許可を得たシステムだけを対象にし、決済サービスではテストモードを使ってください。

サーバー側の秘密情報がブラウザに含まれていないか確認

デプロイ済みサイトを開き、ブラウザの開発者ツールでSources、Network、Storageを確認してください。Supabaseの公開キーなどは意図的に公開されています。sb_secret_...、旧service_role、Stripeのsk_live_...whsec_...、秘密鍵は、ブラウザ側に決して含めてはいけません。

Next.jsでは、静的参照値のような process.env.NEXT_PUBLIC_NAMEnext build 時にブラウザバンドルに埋め込まれます。そのビルドが別の環境に移行しても固定のままです。動的な参照のような process.env[varName] は自動的に埋め込まれませんが、秘密情報を隠すには安全ではありません。サーバー専用の値には NEXT_PUBLIC_ プレフィックスを付けず、サーバーコードのみで読み込むようにしてください。

現在のディレクトリに .env ファイルがないことはほとんど意味しません。ソースコード、生成されたバンドル、Git履歴、CI/CD、デプロイメントプラットフォームの環境変数、ログを検索してください。上の検索パターンは出発点にすぎません。専用のシークレットスキャナーやGitHubのアラートも併用してください。


rg -l --hidden --glob '!.git/**' --glob '!node_modules/**' \
  '(sb_secret_|SUPABASE_SERVICE_ROLE_KEY|service_role|sk_(live|test)_|sk-proj-|gh[pousr]_|github_pat_|AKIA[0-9A-Z]{16}|whsec_|BEGIN ([A-Z ]+ )?PRIVATE KEY)' .

このコマンドが調べるのは現在のチェックアウトだけです。パターンとの一致は検索しますが、出力するのはファイル名だけで、一致した値そのものは表示しません。別のツールでGit履歴全体をスキャンし、素の値を出力しないようにするか、GitHubの秘密情報スキャンを使用してください。実際の秘密情報が漏れた場合は、見た目を整える前に失効対応を優先します。代替キーを発行し、すべての利用箇所を移行し、古い資格情報を無効化してから、リポジトリ履歴を処理してください。完全なシークレットを検索レポートやチケットに貼らないでください。

2人のユーザーで認可境界を越えるテストを行う

テストアカウントAとBを作り、次のケースを試してください。

ボタンを隠すだけでは認可になりません。サーバーとデータベースはすべてのリクエストでセッション、ロール、オブジェクト所有権を検証する必要があります。

Supabaseでは、Data APIへの公開範囲、anonauthenticatedに付与されたGRANT権限、既存のRLSポリシーをまとめて確認してください。RLSが制限するのは許可されたであり、列を隠すものではありません。メールアドレスや内部メモなどの制限対象フィールドは、カラム権限、必要な列だけを公開する安全なビュー、またはサーバーAPIの背後に置きます。既存のpermissiveポリシーは新しいポリシーとOR条件で合成されるため、using (true)のような広いルールも確認してください。

CORSとCSRFを別々に確認

CORSはブラウザがクロスオリジンレスポンスを読み取る方法を制御します。これは認証や認可ではありませんし、すべてのリクエストをブロックすることもありません。許可リストと完全に一致するOriginに対してだけ Access-Control-Allow-Origin を返してください。クッキーが必要な場所のみ Access-Control-Allow-Credentials: true を使用してください。レスポンスヘッダーがリクエストオリジンによって異なれば、Vary: Origin を送信し、キャッシュが異なるオリジンのレスポンスを混ぜないようにしてください。

クッキー認証された POSTPUTPATCH、および DELETE リクエストでは、フレームワークのCSRF保護または確立されたCSRFトークンパターンを使用し、Origin を検証してください。読み取り専用の GET は状態を変更してはいけません。SecureHttpOnly、そして適切な SameSite 設定はセッションクッキーを強化しますが、CSRFトークンを置き換えるには通常はなりません。

StripeのWebhookなどの外部呼び出しエンドポイントは、通常のCSRFトークンチェックから除外される場合があります。例外の範囲をそのルートだけに限定し、有効なStripe署名の検証を必須にします。

入力を受け入れるときと表示するときに検証

文字列 <script> を文字通り保存するだけでは、脆弱性を証明しません。サーバーで長さ、型、形式、範囲を検証し、保存した値は、HTML、URL、JavaScriptなど実際の出力先に合わせてエンコードしてください。

ステージングでは、特殊文字、長すぎる値、上限・下限の境界値を送信してください。それらが他の場所で無害なテキストのままであることを確認してください。また、エラーレスポンスがSQL、内部ファイルパス、スタックトレースを漏らさないことを確認してください。

rawリクエストから重複配信まで決済をテスト

ユーザーはブラウザが送信する価格や数量値を変更できます。信頼できる製品IDからサーバーで再計算し、許可する数量の範囲もサーバー側で適用してください。ブラウザに成功メッセージが出たことを根拠にせず、決済事業者のWebhookを検証した後にだけ注文ステータスを変更してください。

Stripeの署名検証には、解析や再シリアル化を行う前のraw request bodyStripe-Signatureヘッダー、そのエンドポイントの署名シークレットが必要です。グローバルなJSONパーサーがWebhookルートに到達する前にボディを変更しないことを確認してください。

署名検証やキュー挿入などの署名検証やキューへの登録など、同期処理が必要な最小限の作業を終えたら、すぐに2xxを返します。時間のかかる処理は非同期ジョブへ移してください。Webhookは複数回送信される可能性があります。処理された event.id 値を記録してください。別のイベントが同じオブジェクトを参照する可能性があるため、event.typedata.object.id も確認してください。データベースの一意性制約とトランザクションを使い、注文や決済の更新処理が再実行されても結果が一度だけ反映されるようにしてください。StripeAPIのPOSTをサーバーが再試行する場合、同じ操作に同じidempotencyキーを再利用してください。

テストモードでは、変更された金額、無効な署名、同じイベントの再配信、順不同の配信、ダウンストリーム処理失敗後の再試行をテストしてください。

重要な操作にレート制限を設け、パスワードは適切に保存

登録、ログイン、パスワードリセット、検証コード、有料APIにはリクエスト制限が必要です。IPだけの制限では、共有ネットワークや分散攻撃に十分対応できません。アカウント、IP、操作ごとに制限を設計し、429レスポンスとユーザー向けメッセージを検証してください。

パスワードを自前で保存する必要がある場合、OWASPが第一候補としているのはArgon2idです。Argon2idが利用できない場合はscryptを検討し、bcryptはレガシーシステムとの互換性が必要な場合に限って使ってください。平文、復号可能な形で暗号化したパスワード、高速な汎用ハッシュは適切ではありません。マネージド認証を使っても、アプリケーション側の認可、セッションの有効期限、ログイン後のリダイレクト設定は自分で確認する必要があります。

ログには調査の手掛かりを残し、秘密情報は残さない

ブラウザコンソールとサーバーログで AuthorizationCookie ヘッダー、アクセストークンとリフレッシュトークン、セッションID、パスワード、データベース接続文字列、プライベートキー、決済カード情報を検索してください。これらの値をログにしないでください。安定した参照が必要な場合は識別子をマスクまたはハッシュしてください。個人データ(メールアドレスなど)については運用上の必要性、保存期間、アクセス制御を定義し、必要な情報のみを保持してください。

認証失敗、認可拒否、キーまたは権限の変更、支払い状態の変化を一貫してログしてください。時間、結果、内部ユーザーまたはリクエストIDは、資格情報を漏らさずに監査記録を残せます。ログを読めるユーザーと保存期間をレビューしてください。

修正後も同じ失敗リクエストを繰り返す

漏洩した秘密情報はすぐに無効化する必要があります。RLS、GRANT、アプリケーションコードのように同時変更が必要な項目は、慎重に管理してリリースします。ステージングで一式を検証し、短いデプロイ手順を文書化して、ロールバック方法を用意してください。

デプロイ後は、未ログイン時、アカウントA・B間の認可、CSRF、決済の成功・失敗・重複配信について、同じテストをもう一度実行してください。この確認項目をすべて通っても、製品に脆弱性がないことの証明にはなりません。公開サービスが個人データや支払いを処理する場合、独立したレビューを依頼し、明確な範囲を設定してください。