「フィルター」と「ウォール」の違い

あなたはデータにアクセスできるAIエージェントを構築しています。セキュリティには2つの選択肢があります。データを「フィルター」するか、あるいは「ウォール(壁)」で囲むかです。

フィルターとは、クエリが特定の行のみを返すことを意味します。 ウォールとは、エージェントが隠された行に全く到達できないことを意味します。

これらは、何かが壊れるまでは同じように見えます。

最近、私は120万語をナレッジベースに変換するシステムを構築しました。データの管理にはSupabaseを使用しました。AIエージェントには公開コンテンツのみを見せたいと考えていました。

私は、データをフィルタリングするために標準的なPostgresビューを使用しました。

CREATE VIEW public_seeds AS
  SELECT * FROM moments
  WHERE visibility = 'public'
    AND is_canonical = true;

これは正しく見えます。しかし、重大な欠陥があります。デフォルトでは、Postgresのビューは呼び出し者ではなく、所有者として実行されます。ビューの所有者は多くの場合、フルアクセス権限を持っています。つまり、行レベルセキュリティ(RLS)ポリシーがビューに適用されないのです。

あなたが構築したのはウォールではなく、フィルターです。

フィルターが失敗しても、AIエージェントは気づきません。人間ならエラーや誤ったデータに気づきますが、エージェントは受け取ったものをそのまま処理します。フィルターが失敗すると、エージェントは警告なしにプライベートなデータを使用し始めてしまいます。

Postgres 15は、security_invokerオプションによってこれを解決しました。

security_invokertrueに設定すると、ビューは呼び出しロールとして実行されます。これにより、ビューは強制的にRLSポリシーに従うようになります。ビューは構造的なゲート(門)となります。

正しい方法:

CREATE VIEW public_seeds
  WITH (security_invoker = true)
AS
  SELECT * FROM moments
  WHERE visibility = 'public'
    AND is_canonical = true;

これでウォールは構造的なものになりました。たとえ開発者が不適切なクエリや結合(join)を書いても、RLSポリシーがテーブルを保護します。

「このようなことは起こるはずがない」は、すべてが完璧に動作することに依存しています。 「このようなことは起こり得ない」は、あなたのアーキテクチャに依存しています。

AI向けに構築する場合、「起こり得ないこと」を想定して設計しなければなりません。

セットアップで確認すべき3つのこと:

Source: https://dev.to/chadtdyar/the-difference-between-this-shouldnt-happen-and-this-cannot-happen-in-ai-content-pipelines-1g0p

Optional learning community: https://t.me/GyaanSetuAi