Lovable はリリース時に基本的なセキュリティ スキャンを実行しますが、自動スキャンではビジネスの承認が正しいことを証明できません。
特に Supabase プロジェクトの場合、テーブル上の「RLS が有効である」と「ポリシーは権限を超えない」は別のことです。
まず明確なアイデンティティとデータ境界を描画します
匿名ユーザー、ログインユーザー、管理者、およびバックグラウンドタスクをリストします。
次に、各テーブルの所有者フィールドとテナント フィールドをリストします。
|
|
明確な所有権フィールドのないテーブルに対して信頼性の高い戦略を記述することは困難です。
各ビジネス テーブルで RLS が有効になっていることを確認します
Supabase SQL Editor で実際のステータスをクエリします。
|
|
RLS は、新しいテーブルを追加するときに最も見逃しやすくなります。
結果をオンライン監査の添付ファイルとして保存します。
戦略は 4 つの操作をそれぞれカバーする必要があります
SELECT、INSERT、UPDATE、DELETE ではリスクが異なります。
自分の行の読み取りを許可しても、すべてのフィールドの変更を許可する必要があるというわけではありません。
挿入時に新しい行の所有権を確認するには、WITH CHECK を使用します。
更新するときは、古い行の可視性と新しい行の正当性を同時にチェックします。
削除操作には通常、より厳格なロールが必要です。
マルチテナント戦略の user_id を単に比較しないでください
チーム製品はメンバーシップ テーブルに依存することがよくあります。
ポリシーでは、現在のユーザーがターゲット組織に属していることを確認する必要があります。
また、メンバーのステータスが有効かどうか、およびロールが操作を許可しているかどうかも確認してください。
非アクティブ化されたメンバーは、古いテナント データを読み続けないでください。
招待記録は正式メンバーと同等ではありません。
2 つのアカウントを使用して不正なテストを実行する
テナントAのユーザーAliceとテナントBのユーザーBobを作成します。
アリスに識別可能なテスト記録を作成してもらいます。
ボブは、リスト クエリ、ID によるクエリ、レコードの更新、および削除を試みます。
UI をテストするだけではありません。
ブラウザ開発者ツールでリクエストをコピーし、リソース ID を置き換えて再実行します。
すべての未承認のリクエストは空の結果または承認エラーを返す必要があります。
サービス ロール キーをフロントエンドに入力してはなりません
これは RLS をバイパスし、制御されたサーバー上にのみ存在する必要があります。
リポジトリを検索して製品をビルドします。
|
|
以前に送信されたことがある場合は、ファイルを削除するだけでは終了しません。
キーをすぐにローテーションし、Git 履歴とデプロイメント ログを確認する必要があります。
Anon Key は公開できますが、権限を緩和することはできません
Supabase anon キーはもともとクライアント側で使用されます。
そのセキュリティは、RLS とデータベースのアクセス許可に依存しています。
公開されているという理由だけでリクエストが悪用された場合のコストを無視しないでください。
高コストインターフェイス用のレート制限と検証コードを追加しました。
ストレージにも独立した戦略が必要です
バケットがパブリックかプライベートかを確認します。
プライベート ファイルは、有効期間が短い署名付き URL を使用します。
オブジェクト パスには、信頼できるユーザーまたはテナントのプレフィックスが含まれていることが望ましいです。
クライアントのファイル名だけから所有権を推測しないでください。
別のテナントのオブジェクト パスをダウンロード インターフェイスに渡してみます。
エッジ関数はパラメータを信頼する代わりにトークンを検証します
この関数は、Authorization ヘッダーからユーザーを認証する必要があります。
ID の根拠としてリクエスト本文の user_id を受け入れないでください。
管理者のアクションにより、サーバー側でロールが再クエリされます。
完全な JWT、Cookie、または支払い情報をログに出力しないでください。
データベース機能チェック SECURITY DEFINER
|
|
SECURITY DEFINER` この関数は所有者の権限で実行されます。
search_path を修正し、実行権限を制限し、動的 SQL をレビューする必要があります。
必要がない場合は、デフォルトの呼び出し元権限に戻します。
フロントエンドの隠しボタンは許可されていません
生成された愛らしいページは、役割に基づいて管理ボタンを非表示にする場合があります。
攻撃者は引き続き API を直接呼び出すことができます。
すべてのアクセス許可をデータベース ポリシーまたはサーバー側で再度強制する必要があります。
UI の判断はエクスペリエンスを向上させるだけであり、セキュリティ境界を構成するものではありません。
リリース前に陰性検査を実施する
ログイン アクセスなしでテストします。
期限切れのトークンをテストします。
一般ユーザーが管理者インターフェイスを呼び出すことをテストします。
クロステナント UUID をテストします。
テスト バッチ インターフェイスに不正なレコードが混在しています。
非常に大きなファイルのアップロードと MIME タイプの偽造をテストします。
削除されたアカウントの古いトークンをテストします。
すべてのネガティブなユースケースが合格した場合にのみ、ポリシーが通常のパスをカバーするだけではないことを意味します。
問題発見後の処理の流れ
まずポリシーを強化するか、影響を受ける機能を一時停止してください。
漏洩したキーを再ローテーションします。
監査ログをチェックして、悪用されていないか確認してください。
修正後、2 つのテナントで再テストします。
ついにフロントエンドが再リリースされました。
セキュリティの問題を、「もう少し最適化する」という新しい自然言語プロンプトに任せるだけではありません。
最終チェックリスト
-
すべてのビジネス テーブルの RLS ステータスがエクスポートされました。
-
4 種類のデータベース操作には明確な戦略があります。
-
マルチテナント認証はメンバーシップ検証に合格します。
-
サービス ロール キーがクライアントまたは Git に入力されません。
-
ストレージ バケットとオブジェクト ポリシーがテストされました。
-
エッジ機能は、アイデンティティと役割を独立して検証します。
-
SECURITY DEFINER 関数を 1 つずつ確認します。
-
2 つのアカウント未承認テストは、読み取り、書き込み、削除を対象としています。
-
キーのローテーションおよびイベント応答パスは実行可能です。
自動スキャンは、一般的な構成エラーを見つけるのに適しています。マルチテナントのビジネス ルールでは、依然として手動の設計と敵対的テストが必要です。
超基地の安全性情報
インターフェイスを確認するだけでなく、SQL を使用して既存のポリシーを表示します
|
|
結果をエクスポートしたら、表ごとに結果を確認します。 qual はどの古い行を表示するかを決定し、with_check は書き込み後の新しい行の存在を許可するかどうかを決定します。いずれか 1 つだけを書き込むと、読み取りと書き込みのルールが非対称になる可能性があります。
マルチテナント読み取り戦略のアイデアを確認する
|
|
実際の戦略では、役割とビジネス ニーズを組み合わせる必要もあります。レビューするときは、organization_id にインデックスがあることを確認してください。そうでないと、クエリごとにメンバーシップがスキャンされ、セキュリティ ポリシーがパフォーマンスのボトルネックになる可能性があります。
ユーザーが所有権フィールドを変更できないようにする
ユーザーにタイトルの更新を許可する場合、ユーザーが owner_id または organization_id を他の値に変更することも許可すべきではありません。列への更新を制限したり、WITH CHECK での所有権が合法であることを要求したりすることができます。
API テストでは、所有権フィールドが表示されないフロントエンド フォームに依存するのではなく、所有権フィールドを明示的に送信する必要があります。攻撃者は JSON リクエストを直接作成する可能性があります。
招待プロセスにおける競合状態
チームへの招待には、少なくともランダムなトークン、有効期限、対象の電子メール、組織、およびステータスが含まれています。招待を受け入れるときに、データベース トランザクションで使用されるトークンをチェックしてマークします。
同じ招待リンクを同時に 2 回送信しても、作成できるメンバーシップは 1 つだけです。取り消された、または期限切れになった招待は失敗する必要があり、ユーザーがログインしているからといってチェックをスキップすることはできません。
ストレージはアップロード後に二次検証を実行します
クライアントのContent-Typeは偽造可能です。サーバーまたは非同期タスクは、ファイル ヘッダーを読み取り、実際の形式を確認し、画像、PDF、およびその他のタイプに独立したサイズ制限を設定します。
パブリック バケットには、ID カード、契約書、ユーザー エクスポート ファイルは保存されません。プライベート バケットの署名付き URL の有効期間は短く、ログには完全な署名付き URL は記録されません。
エッジ機能の CORS は許可されていません
CORS は、ブラウザーがクロスドメイン応答を読み取ることができるかどうかのみを制御し、curl またはサーバーの要求を防ぐことはできません。関数では、JWT、テナント メンバーシップ、および特定の操作権限を検証する必要があります。
プリフライトリクエストは、必要なメソッドとヘッダーのみを返します。ブラウザーのエラーを排除するために、オリジンと資格情報を組み合わせて使用しないでください。
バックアップには機密データも含まれています
Supabase バックアップ、SQL ダンプ、およびローカル torrent ファイルは、運用データと同じ保護レベルを使用します。開発用コンピューターにダウンロードする前に、ディスクの暗号化とアクセス許可を確認してください。
復旧訓練では隔離アイテムを使用します。リカバリが完了するとすぐに、テスト環境のデータとともに持ち込まれたトークン、Webhook シークレット、およびサードパーティの認証情報がローテーションされます。
オンライン化後の継続的な検査
RLS 拒否の数、異常なバッチ読み取り、ストレージ トラフィック、およびエッジ機能のエラー率を監視します。 1 回の拒否は通常は通常の入力エラーですが、短期間に多数の UUID を走査する場合は不正な検出である可能性があります。
セキュリティ チェックリストは、新しいテーブル、バケット、または関数が追加されるたびに再実行されます。最初のオンライン監査に合格したからといって、それ以降に生成されるすべての関数が自動的に正しいポリシーを継承するわけではありません。