TL

iframeサンドボックスと権限分離の境界

埋め込んだ第三者コンテンツを安全に閉じ込められる。sandbox属性が無効化する能力、allow-same-originが境界を壊す理由、Permissions Policyとの併用で隔離を設計する勘所を原理から押さえます。

応用セキュリティWebiframeブラウザ権限分離最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.sandbox属性を付けた瞬間、iframeはスクリプト実行・フォーム送信・ポップアップ・トップレベル遷移・同一オリジン扱いを一括で失う。allow-トークンで能力を1つずつ戻していく減算モデル。
  • 2.allow-same-origin と allow-scripts を同時に許すと、内側のスクリプトが自分のsandbox属性を消して再読み込みでき、サンドボックスを自力で破れる。同一オリジン埋め込みでは特に危険。
  • 3.sandbox は能力(API面)の無効化、Permissions Policy はカメラ等の強力機能の許可委譲、CSPのframe系は誰を埋め込む/誰に埋め込まれるかを制御。3層を重ねて初めて隔離が成立する。

iframe は別ドキュメントを現在のページに埋め込む仕組みですが、埋め込む相手が広告・ウィジェット・ユーザー投稿の HTML など信頼できないコードであることは珍しくありません。sandbox 属性は、その埋め込みフレームから危険な能力を奪い、限定的な実行環境に閉じ込めるための機能です。ここでは各トークンが何を無効化するのか、なぜ allow-same-origin が境界を壊すのか、そして Permissions Policy や CSP との役割分担を原理から見ていきます。

sandbox は「全部禁止」から始まる減算モデル

最大のポイントは、sandbox 属性を付けた時点でフレームの能力がほぼすべて無効化されることです。何も値を書かない <iframe sandbox src="..."> は最も制限が強く、そこから sandbox="allow-scripts allow-forms" のように allow- トークンを並べて、必要な能力を1つずつ戻していきます。CSP のような「許可リストを足していく」発想に似た、加算ではなく減算のモデルです。

<!-- 最も厳しい: スクリプトもフォームも遷移もすべて不可 -->
<iframe sandbox src="https://untrusted.example/widget"></iframe>

<!-- スクリプトとフォーム送信だけ戻す -->
<iframe sandbox="allow-scripts allow-forms"
        src="https://untrusted.example/widget"></iframe>

空の sandbox を付けたフレームは、内部的に**不透明オリジン(opaque origin)**を割り当てられます。これは「どのオリジンとも一致しない、生成のたびに異なる一意のオリジン」で、自分自身とも同一オリジンになりません。結果として、そのフレーム内のスクリプトは自身の localStoragesessionStoragedocument.cookie、IndexedDB などオリジン紐付けのストレージに一切アクセスできなくなります。オリジンが何を意味するかは 同一オリジンポリシーとサイト分離の信頼境界 の通りで、sandbox はその境界を「最も孤立した側」に倒す操作だと捉えると理解しやすいです。

各トークンが無効化/復帰させる能力

主要なトークンと、それが制御する能力を整理します。

トークン戻る能力省略時に起きること
allow-scriptsJavaScript の実行script が一切動かない(自動再生・計測も止まる)
allow-formsフォームの送信submit がブロックされる
allow-same-origin本来のオリジンとして扱う不透明オリジン化しストレージ/Cookie 不可
allow-popupswindow.open 等での新規ウィンドウポップアップが開けない
allow-top-navigationトップレベル(親)の遷移フレームが親ページを別URLへ飛ばせない
allow-modalsalert/confirm/print 等のモーダルこれらの呼び出しが無視される
allow-downloadsファイルのダウンロード開始ダウンロードが抑止される

特に注意したいのが トップレベル遷移 です。allow-top-navigation を与えないと、サンドボックス内のスクリプトは top.location = '...'target="_top" のリンクで親ページごと別サイトへ飛ばすことができません。広告フレームがユーザーを勝手にフィッシングサイトへリダイレクトする典型的な攻撃は、これで遮断されます。より安全な中間として allow-top-navigation-by-user-activation があり、これは実際のクリックなどユーザー操作を伴うときだけトップ遷移を許します。自動リダイレクトは止めつつ、正規のリンククリックは通したい広告枠などで使われます。

allow-popups-to-escape-sandbox の意味

allow-popups で開いた新しいウィンドウは、既定では親フレームと同じ sandbox 制約を継承します。allow-popups-to-escape-sandbox を併記すると、その継承を断ち切り、ポップアップ先を制約なしのウィンドウとして開けます。逆に言えば、これを安易に付けると「サンドボックスの外」へ抜ける口を自ら開けることになるため、信頼できない埋め込みでは避けます。

allow-same-origin が境界を壊す理由

allow-same-origin は他のトークンと性格が違います。これは能力を1つ足すというより、フレームを不透明オリジンから本来のオリジンへ戻すスイッチです。これを付けると、フレームは本来のオリジンとして扱われ、同一オリジンであれば Cookie・ストレージ・postMessage を超えた DOM 直アクセスまで可能になります。

危険なのは allow-same-originallow-scripts同時に許す場合です。両方が揃うと、フレーム内のスクリプトは自分が埋め込まれている <iframe> 要素の DOM へ(同一オリジンなら)アクセスでき、自分自身の sandbox 属性を書き換えてから再読み込みを誘発できます。属性の評価は次回ロード時に効くため、sandbox を緩めた状態で読み直すことで、自力でサンドボックスを脱出できてしまいます。さらに同一オリジンを名乗れる以上、親ページのストレージや Cookie とオリジンを共有し、サンドボックスの「隔離」という前提自体が崩れます。

同一オリジン埋め込み × 2トークン同時許可は実質サンドボックスなし

信頼できないコンテンツを自サイトと同一オリジンsandbox="allow-scripts allow-same-origin" 埋め込みするのは、ほぼサンドボックスを無効化したのと同じです。脱出に加え、同一オリジンの DOM 直アクセスで親の機密も読まれ得ます。信頼境界が要るコンテンツは、専用の別オリジン(例: usercontent.example のような分離ドメイン)に置き、そのうえで sandbox を掛けるのが定石です。こうすれば allow-same-origin を付けても、共有されるのはその分離オリジン内に限られます。

sandbox・Permissions Policy・CSP の役割分担

iframe の隔離は1つの属性では完結せず、性質の異なる3つの仕組みを重ねて設計します。

仕組み制御する対象向き
sandbox 属性スクリプト/フォーム/遷移などフレームの基本能力親 → 埋め込むフレーム
allow 属性 (Permissions Policy)カメラ/マイク/位置情報など強力機能の委譲親 → 埋め込むフレーム
CSP frame-srcどの URL を iframe で読み込んでよいか親が自分の埋め込み先を制限
CSP frame-ancestorsどのページが自分を iframe 化してよいか子が自分の埋め込まれ方を制限

sandbox が「フレーム内でできる操作」を能力レベルで削るのに対し、<iframe>allow 属性が指定する Permissions Policy は、カメラ・マイク・位置情報・全画面・支払いといった強力機能の利用許可をフレームへ委譲するかどうかを制御します。両者は補完関係です。たとえばカメラを使うウィジェットなら sandbox="allow-scripts" で能力を絞りつつ、allow="camera" で必要な機能だけを明示的に渡します。allow で渡さない限り、たとえ allow-scripts でスクリプトが動いても getUserMedia() は権限拒否になります。

<iframe
  sandbox="allow-scripts allow-forms"
  allow="camera; microphone 'none'; geolocation 'none'"
  src="https://untrusted.example/recorder">
</iframe>

CSP 側は埋め込み関係そのものを制御します。親が frame-src で「自分が読み込んでよい iframe の URL」を制限し(Content Security Policy の内部動作と回避耐性 で扱う default-src フォールバックも効きます)、逆に埋め込まれる側は frame-ancestors で「自分を iframe に入れてよい親」を制限してクリックジャッキングを防ぎます。frame-ancestors 'none' は旧来の X-Frame-Options: DENY の後継で、CSP として一元管理できる点が利点です。

postMessage と Storage Access の併用

サンドボックス化したフレームと親が連携する正規ルートは postMessage です。送信側は第2引数で受信オリジンを厳密に指定し、受信側は event.origin を必ず検証します。なお不透明オリジンや別オリジンのフレームは Web ストレージ(localStorage / sessionStorage) を親と共有しないため、状態はメッセージで受け渡すか、ユーザー操作を起点とする Storage Access API 経由に限定する設計が安全です。

設計の指針 — 最小権限で組み立てる

実務での組み立て方は明快です。まず値なしの sandbox から始め、そのコンテンツが本当に必要とする能力だけallow- で戻します。スクリプトが要るなら allow-scripts、フォームが要るなら allow-forms、というように加算は最小限にとどめます。allow-same-origin は、信頼できないコンテンツに対しては原則付けない。どうしてもストレージ等が要るなら、必ず専用の分離オリジンに隔離したうえで付けます。

そのうえで Permissions Policy の allow で強力機能を絞り、CSP の frame-srcframe-ancestors で埋め込みの両方向を固めます。信頼できない HTML を直接描画する場面では、サンドボックス化フレームへの注入経路そのものも DOM-based XSS の sink/source 分類と緩和原理 の観点で塞いでおくべきです。sandbox 単体に頼らず、能力の無効化・機能委譲・埋め込み制御の3層を重ねることが、第三者コンテンツを安全に同居させる唯一の堅い設計です。

Web/フロントエンド Article

iframeサンドボックスと権限分離の境界を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

セキュリティ

比較で見る軸

難易度: advanced / カテゴリ: Web/フロントエンド / タグ数: 5

導入後に効く点

allow-same-origin と allow-scripts を同時に許すと、内側のスクリプトが自分のsandbox属性を消して再読み込みでき、サンドボックスを自力で破れる。同一オリジン埋め込みでは特に危険。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
Web/フロントエンド
タグ数
5

判断チェックリスト

  • 自社の用途が「セキュリティ / Web」に近いか確認する。
  • 強みである「sandbox属性を付けた瞬間、iframeはスクリプト実行・フォーム送信・ポップアップ・トップレベル遷移・同一オリジン扱いを一括で失う。allow-トークンで能力を1つずつ戻していく減算モデル。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

セキュリティWebiframeブラウザ権限分離セキュリティWebiframe
参考: 公式情報