安全性 NEW 2026.07.08 追加

メモリポイズニング

めもりぽいずにんぐ

悪意ある内容をエージェント記憶に書き込み、セッションを跨いで行動を操作する攻撃手法。

メモリポイズニング

メモリポイズニングとは

メモリポイズニングは、悪意ある攻撃者が AI エージェントの長期記憶(ベクターストア・会話履歴・スクラッチパッド)に不正なインストラクションを書き込み、将来のセッションでエージェントの行動を操作する攻撃手法だ。従来のプロンプトインジェクションがセッション終了とともにリセットされるのに対し、メモリポイズニングは攻撃の効果がセッションをまたいで持続し、トリガーとなる入力から時間的に切り離された状態で実行される点が特徴的だ。

OWASP は 2026 年に「OWASP Top 10 for Agentic Applications」を策定し、メモリ・コンテキストポイズニングを ASI06 として分類した。エージェントが参照するドキュメント・ウェブページ・RAG インデックスのいずれかに悪意あるコンテンツを混入させるだけで攻撃が成立し、研究では 80〜99.8% の攻撃成功率が報告されている。

なぜ注目されているのか

エージェントが長期記憶を持つことで実現できる「コンテキストの継続性」は、同時に攻撃のターゲットになる。攻撃者はエージェントが処理する外部ドキュメントに一度だけ不正なインストラクションを埋め込めば、その内容がエージェントの記憶に取り込まれ、数日後や別ユーザーとのセッションで実行される可能性がある。Claude Code や Cursor のような自律型コーディングエージェントが普及するほど、この脅威の影響範囲は広がる。

既存のプロンプトインジェクション対策(入力モデレーション・出力フィルタリング・セッション監視)はリセットを前提とした設計であるため、永続的な攻撃に対しては有効性が低い。防御には、メモリ書き込み時の出所追跡・信頼スコアリング・読み出し前の内容検証を組み合わせたレイヤードアプローチが必要とされている。

関連する技術

プロンプトインジェクションと攻撃の起点は共通しているが、持続性の有無で区別される。メタハーネスのような複数エージェントを束ねる構成では、単一エージェントのメモリが汚染されると他のエージェントにも影響が伝播するリスクがあり、アーキテクチャレベルでのメモリ分離設計が重要になる。

ドラゴンボールで例えると

メモリポイズニングはバビディの魔人化魔法そのものだ。

ドラゴンボールで最も厄介だったのは「操られた戦士が仲間に牙を向く」ことだった。エージェントにとっての外部ドキュメントも、一見無害に見えて悪意が潜んでいる場合がある。

実装してみる

▸ CLAUDE CODE
  1. 01
    エージェントが使用するメモリストア(ベクターDB やファイル)への書き込みをラップする検証レイヤーを作成する
  2. 02
    書き込み時にコンテンツの出所(URL・ユーザーID・タイムスタンプ)をメタデータとして付与する
  3. 03
    読み出し時に信頼スコアの低いメモリをフィルタリングするガード関数を追加する
  4. 04
    Claude Code に下記プロンプトを渡してサニタイザーを実装させる
SHELL
# メモリサニタイザーの雛形を Claude Code で生成する
claude "エージェント用メモリストアへの読み書きをラップし、書き込み時はソース・タイムスタンプ・信頼スコアをメタデータとして付与し、読み出し時は信頼スコアが閾値以下のエントリをフィルタリングする TypeScript モジュールを実装してください。RAG ベクターストアとファイルベースの両方に対応すること。"
memory-guard.ts(生成例)
interface MemoryEntry {
  content: string;
  metadata: {
    source: string;
    timestamp: string;
    trustScore: number; // 0.0 - 1.0
  };
}

const TRUST_THRESHOLD = 0.7;

export function writeMemory(store: Map<string, MemoryEntry>, key: string, content: string, source: string) {
  const trustScore = source.startsWith('user:') ? 0.5 : 0.9;
  store.set(key, {
    content,
    metadata: { source, timestamp: new Date().toISOString(), trustScore },
  });
}

export function readMemory(store: Map<string, MemoryEntry>): MemoryEntry[] {
  return [...store.values()].filter(e => e.metadata.trustScore >= TRUST_THRESHOLD);
}
PROMPT例 — そのまま貼り付け可
エージェントの長期記憶への書き込み前にコンテンツを検証し、不審なインストラクション(命令形・ロール変更・システムプロンプト上書きを示すパターン)が含まれていればブロックまたはフラグを立てるサニタイザー関数を TypeScript で実装してください。信頼スコアは出所ドメインとコンテンツパターンで算出し、RAG ベクターストアへの書き込みと読み出し両方をラップすること。

出典