HyperGen

ADR-004: セキュリティモデル — サンドボックス化されたiframe + HTMX

HyperGenはエージェント生成HTMLをサンドボックス化されたiframe内にレンダリング。HTMXがサンドボックス内でインタラクティビティを処理し、postMessageがiframeとホストをブリッジ。

ステータス: 承認済み 日付: 2026-03-28


コンテキスト

HyperGenのコア設計(ADR-001)は、AIエージェントがHTMX属性付きのHTMLを生成することを確立しています。このHTMLはクライアントアプリケーションのどこかにレンダリングされなければなりません。レンダリング戦略はセキュリティに直接影響します:

  • 直接DOMインジェクション(ホストページにHTMLを注入)— 最大の統合性だが、エージェント生成HTMLがホストのDOM、Cookie、localStorage、すべてのJavaScript APIにフルアクセス。生成HTML内の単一XSSベクターでアプリケーション全体が危殆化。
  • サンドボックス化されたiframe(分離されたiframe内にHTMLをレンダリング)— 強力なセキュリティ境界。生成HTMLはホストのDOMやストレージにアクセス不可。統合にはpostMessage経由の明示的なブリッジが必要。

ClaudeのGenerative UIとMCP Appsはどちらもサンドボックス化されたiframeを使用しています。このアプローチは実戦で検証済みであり、ブラウザのセキュリティプリミティブと一致しています。


決定

HyperGenはエージェント生成UIをサンドボックス化されたiframe内にレンダリングします。HTMXはiframe内で動作し、HTTP/SSE経由でエージェントサーバーと直接通信。ホストアプリケーションはiframeとpostMessage経由で通信。

アーキテクチャ

┌─────────────────────────────────────────────┐
│  ホストアプリケーション                       │
│                                             │
│  ┌───────────────────────────────────────┐  │
│  │  サンドボックス化された <iframe>        │  │
│  │                                       │  │
│  │  ┌─────────────┐    ┌─────────────┐  │  │
│  │  │  HTMX       │    │  エージェント │  │  │
│  │  │  (14KB)     │    │  HTML+CSS+JS │  │  │
│  │  └──────┬──────┘    └─────────────┘  │  │
│  │         │                             │  │
│  │         │ hx-get / hx-post / SSE      │  │
│  │         ▼                             │  │
│  │  ┌─────────────┐                     │  │
│  │  │ エージェント │ (HTTP / SSE)        │  │
│  │  │ サーバー    │                     │  │
│  │  └─────────────┘                     │  │
│  │                                       │  │
│  └────────────────┬──────────────────────┘  │
│                   │ postMessage               │
│                   ▼                           │
│  ┌─────────────────────────────────────────┐│
│  │  ホストJavaScript(イベントリスナー)    ││
│  └─────────────────────────────────────────┘│
└─────────────────────────────────────────────┘

3つの通信チャネル

チャネル方向目的メカニズム
エージェント → iframeサーバー → クライアントUIフラグメントのストリーム、インタラクションへの応答HTTPレスポンス、HTMX経由のSSE
iframe → エージェントクライアント → サーバーユーザーアクション送信(フォーム送信、ボタンクリック)HTMX hx-get/hx-post(標準HTTP)
iframe ↔ ホスト双方向テーマ注入、リサイズ通知、ナビゲーション、データ受け渡しpostMessage API

Sandboxポリシー

iframeはHTMXが必要とするパーミッションのみの厳格なsandbox属性を使用:

<iframe
  sandbox="allow-scripts allow-same-origin allow-forms"
  src="about:blank"
  style="width: 100%; border: none;"
></iframe>
パーミッション必要な理由
allow-scriptsHTMXがhx-*属性を処理するためにJavaScriptが必要
allow-same-originHTMXがエージェントサーバーにHTTPリクエストを行う必要(同一オリジンまたはCORS)
allow-formsHTMXのフォーム送信(<form>でのhx-post

明示的に付与されないもの:

パーミッション拒否理由
allow-top-navigationiframeがホストページをリダイレクトするのを防止
allow-popupsiframeが新しいウィンドウを開くのを防止
allow-modalsalert()confirm()prompt()がホストをブロックするのを防止
allow-pointer-lockカーソルキャプチャを防止
allow-downloads自動ファイルダウンロードを防止

Content Security Policy

ホストアプリケーションはiframeコンテンツにCSPを設定して機能をさらに制限すべきです (SHOULD):

default-src 'none';
script-src 'self' 'unsafe-inline' https://unpkg.com/htmx.org;
style-src 'self' 'unsafe-inline';
connect-src <agent-server-origin>;
img-src 'self' data: https:;
font-src 'self' data:;

主な制限:

  • script-srcはインラインスクリプトと信頼されたCDNからのHTMXのみを許可
  • connect-srcはHTTP/SSE接続を既知のエージェントサーバーに制限
  • eval()なし、HTMX以外の外部スクリプトロードなし

iframeのライフサイクル

1. 初期化

ホストがサンドボックス化されたiframeを作成し、最小限のブートストラップドキュメントを注入:

<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/htmx.org@2"></script>
  <script src="https://unpkg.com/htmx-ext-sse@2"></script>
  <style>
    :root {
      /* Host theme variables injected here */
    }
    * { box-sizing: border-box; }
    body { margin: 0; font-family: system-ui, sans-serif; }
  </style>
</head>
<body>
  <div id="hg-root"
       hx-ext="sse"
       sse-connect="/api/agent/stream"
       sse-swap="message"
       hx-swap="innerHTML">
    <!-- Agent-generated content streams here -->
  </div>
  <script>
    // postMessage bridge for host communication
    window.addEventListener('message', (e) => {
      if (e.data.type === 'hg:theme') {
        Object.entries(e.data.vars).forEach(([k, v]) => {
          document.documentElement.style.setProperty(k, v);
        });
      }
    });

    // Notify host of size changes for auto-resize
    const ro = new ResizeObserver(() => {
      window.parent.postMessage({
        type: 'hg:resize',
        height: document.body.scrollHeight
      }, '*');
    });
    ro.observe(document.body);
  </script>
</body>
</html>

2. ストリーミング

SSE接続(sse-connect)がエージェントサーバーからHTMLフラグメントをストリーミング。HTMXが処理:

  • フラグメント到着時のプログレッシブレンダリング
  • hx-swap戦略(innerHTMLbeforeendouterHTMLなど)によるDOM更新
  • hx-indicatorによるローディングインジケーター

3. ユーザーインタラクション

ユーザーが生成されたUI(ボタンクリック、フォーム送信)を操作すると、HTMXがエージェントサーバーに標準HTTPリクエストを送信。サーバーはHTMXがDOMにスワップする新しいHTMLフラグメントで応答。エージェントインタラクションにpostMessageのラウンドトリップは不要 — これはiframe ↔ サーバーの直接ループです。

4. ホスト通信

iframe境界を越える必要がある操作:

// iframe内: ナビゲーション意図をホストに通知
window.parent.postMessage({
  type: 'hg:navigate',
  url: '/dashboard'
}, '*');

// iframe内: ホストにデータを送信
window.parent.postMessage({
  type: 'hg:data',
  payload: { selectedItem: 42 }
}, '*');
// ホスト: iframeイベントをリッスン
iframe.contentWindow.addEventListener('message', (e) => {
  if (e.data.type === 'hg:navigate') {
    router.push(e.data.url);
  }
});

// ホスト: iframeにテーマを注入
iframe.contentWindow.postMessage({
  type: 'hg:theme',
  vars: {
    '--hg-surface': '#1a1a2e',
    '--hg-text': '#e0e0e0',
    '--hg-accent': '#7c3aed',
  }
}, '*');

HyperGen vs. MCP Appsセキュリティ比較

側面MCP AppsHyperGen
分離サンドボックス化されたiframeサンドボックス化されたiframe(同じ)
インタラクティビティiframe内のJavaScript(任意)HTMX属性(宣言的) + 最小限JS
エージェント通信JSON-RPC over postMessage → ホスト → サーバーiframe → エージェントサーバーへの直接HTTP/SSE
ストリーミング非サポート(完全ペイロード配信)HTMX経由のSSE(プログレッシブレンダリング)
プロトコル結合MCP必須プロトコル非依存(HTTP + SSEのみ)
ホストブリッジJSON-RPC 2.0 over postMessage型付きイベントによるシンプルなpostMessage

主要なアーキテクチャの違い: MCP Appsはすべてのエージェント通信をホスト経由でルーティング(iframe → postMessage → ホスト → MCPサーバー)。HyperGenはiframeがHTTP/SSE経由でエージェントサーバーと直接通信し、postMessageはホスト統合(テーマ、ナビゲーション、データ受け渡し)のみに使用。これはよりシンプルでストリーミングを可能にします。


脅威モデル

iframeサンドボックスで軽減される脅威

脅威軽減方法
ホストに対するXSSiframeサンドボックスがホストのDOM、Cookie、localStorageへのアクセスを防止
Cookie窃取sandboxallow-same-originなしではCookieを防止; ありの場合はiframeオリジンにスコープ
ホストページナビゲーションallow-top-navigationが付与されない
ポップアップスパムallow-popupsが付与されない
ホスト入力のキーロギングiframeはホストのDOMイベントにアクセス不可

残存リスク

リスク深刻度軽減策
悪意あるエージェントサーバーエージェントサーバーURLはホストが設定。CSP connect-srcで信頼されたエンドポイントのみ許可すべきである (SHOULD)。
HTTP経由のデータ漏洩CSP connect-srcが外向き接続を設定されたエージェントサーバーのみに制限。
iframeフィッシングiframeがホストのログインフォームに見えるコンテンツをレンダリングする可能性。軽減: ホストはiframe領域を視覚的に区別すべき(薄いボーダー、ラベルなど)。
リソース枯渇悪意あるHTMLがCPU/メモリを消費する可能性。軽減: ホストはiframeサイズ制限を設定し、応答しないiframeを破棄可能。
allow-same-originリスクallow-same-originにより、iframeがそのオリジンのCookie/ストレージにアクセス可能。エージェントサーバーがホストと同一オリジンの場合、アクセス範囲が広がる。軽減: エージェントサーバーは別のサブドメインにすべきである (SHOULD)、またはCORSを使用。

結果

ポジティブ

  • デフォルトで強力なセキュリティ。 iframeサンドボックスはブラウザが強制するセキュリティ境界。サニタイズライブラリ不要 — ブラウザが分離を行う。
  • ストリーミングが動作。 MCP Appsと異なり、HTMXのSSE拡張がpostMessageオーバーヘッドなしにiframe内に直接ストリーミング。
  • シンプルなホスト統合。 postMessageは理解しやすい最小限のAPI。JSON-RPCの複雑さなし。
  • エコシステムに馴染みがある。 ClaudeやMCP Appsと同じパターンに従い、既にそのエコシステムにいる開発者が採用しやすい。

ネガティブ

  • iframeレンダリングのオーバーヘッド。 各HyperGenウィジェットが新しいブラウジングコンテキストを作成。多くの小さなウィジェットがあるアプリケーションではパフォーマンスに影響する可能性。
  • CSSの分離は利点でありコストでもある。 iframeのスタイルは完全に分離 — ホストのCSSが漏れ込まないが、ホストのデザインシステムはpostMessage経由のCSS変数で明示的にブリッジする必要がある。
  • クロスオリジンの複雑さ。 エージェントサーバーが異なるオリジンにある場合、CORSの設定が必要。これは標準的だがセットアップの摩擦が増す。

参考資料

目次