サイトにコンテンツを安全に埋め込む

埋め込みコンテンツは、ユーザーをサイトに留めながら、他のページやサイトのコンテンツを共有するのに最適な方法です。Twitter のスタイルと形式で表示される埋め込みツイートと同じくらい小さくてもかまいません。たとえば、Shopify ショップを埋め込み、訪問者がサイトを離れることなく購入できるようにするなど、完全に別のサイトに埋め込まれているサイトのような規模になることもあります。

コンテンツを埋め込む際は、サイトの安全性を保つことがこれまで以上に重要になっています。

デベロッパーがウェブサイトにコンテンツを埋め込む方法はいくつかあります。最も一般的な方法は、URL だけでサイトにコンテンツを埋め込むことができる <iframe> を使用することです。sandbox 属性を追加して iframe のセキュリティを高めることは、すでに可能です。

または、次のような提案された HTML 要素を使用することもできます。

  • <fencedframe> は、サードパーティのコンテンツを埋め込むプライバシー保護の方法として提案されています。
  • よりシームレスなページ遷移を実現するため、<portal> が提案されています。

以下に、埋め込みコンテンツのセキュリティを強化する方法について説明します。

iframe を使った埋め込み

iframe は、地図やフォームを問い合わせページに追加する場合や、広告を表示するなど、あらゆるユースケースで使用できます。

<iframe src="https://example.com/maps"></iframe>

各 iframe には、独自のブラウジング コンテキストと、独自のセッション履歴とドキュメントがあります。iframe を埋め込むコンテキストは、親parentブラウジング コンテキストと呼ばれます。

iframe に表示される第三者のコンテンツは、postMessage() を通じて親サイトとやり取りできます。これにより、デベロッパーはブラウジング コンテキスト間で任意の値を送信できます。メッセージ レシーバは、イベント リスナー onmessage を使用して値を受信できます。

// inside iframe
window.parent.postMessage("ping", "https://example.com");

// window
window.addEventListener("message", (event) => {
  console.log(event.data);
})

sandbox 属性によるセキュリティの強化

悪意のあるコンテンツが iframe にデプロイされると、意図しない操作(JavaScript の実行やフォームの送信など)が実行されるおそれがあります。これを回避するために、sandbox 属性は iframe で実行可能な API を制限し、有害な可能性がある機能を無効にします。

<iframe src="https://example.com" sandbox></iframe>

サンドボックスでは、埋め込みコンテンツにとって重要な API が利用できなくなる場合があります。無効にした API を許可するには、sandbox 属性に引数を明示的に追加します。

<iframe sandbox="allow-forms" src="https://example.com"></iframe>

sandbox 仕様には、allow-formsallow-same-originallow-popups など、多くの有効な値があります。

権限ポリシー

ウェブ向けの機能がますます強化されるにつれ、すべての権限を管理するための権限ポリシーが作成されました。権限ポリシーは、親サイトと iframe コンテンツに適用できます。allow 属性を使用して、親サイトに付与される権限を iframe にも付与できます。

<iframe src="https://example.com" allow="fullscreen"></iframe>

フェンス付きフレームを使用した埋め込み

フェンス付きフレーム<fencedframe>)は埋め込みコンテンツ用に提案された HTML 要素で、iframe と同様です。iframe とは異なり、フェンス付きフレームはエンベディング コンテキストとの通信を制限し、エンベディング コンテキストと共有することなく、フレームがクロスサイト データにアクセスできるようにします。同様に、親ページのファーストパーティ データをフェンス付きフレームと共有することはできません。

<fencedframe src="https://3rd.party.example"></fencedframe>

フェンス付きフレームは、トップレベル サイトでデータを分割するよう提案するプライバシー サンドボックスの提案です。プライバシー サンドボックスの提案の多くは、サードパーティ Cookie やその他のトラッキング メカニズムを使用せずに、クロスサイトのユースケースに対応することを目的としています。一部のプライバシー サンドボックス API では、選択したドキュメントをフェンス付きフレーム内にレンダリングする必要がある場合があります。

たとえば、FLEDGE API 広告オークションの落札者にはフェンス付きフレームが作成されます。FLEDGE API は、フェンスされたフレーム内でレンダリングできる、位置に依存しない URN スキームである不透明ソースを提供します。不透明なソースを使用すると、サイトは広告ソースの URL をサイト所有者に開示せずにサイトにコンテンツを表示できます。

<fencedframe src="urn:uuid:c36973b5-e5d9-de59-e4c4-364f137b3c7a"></fencedframe>

最終的に、フェンス付きフレームが iframe を置き換えることはできません。使用する必要はありません。フェンス付きフレームは、異なるトップレベル パーティションのデータを同じページに表示する必要がある場合に使用する、よりプライベートなフレームとして提案されます。

ポータルを使用した埋め込み

ポータル<portal>)は、独立したブラウジング コンテキストを持つ提案された HTML 要素です。これにより、ページ遷移エクスペリエンスが改善される可能性があります。ポータルには iframe などのコンテンツが埋め込まれていますが、ユーザーはポータルのコードにアクセスできません。ポータルは表示専用であり、ユーザーが操作することはできません。

ポータルは、マルチページ アプリケーションの複雑さを軽減し、シングルページ アプリケーションをシームレスに移行します。この遷移をアニメーション化して、ブラウザ ウィンドウのコンテンツをすばやく置き換えます。

<portal src="https://example.com/"></portal>

ポータルの仕様はまだ開発の初期段階です。

埋め込みに使用されるその他の HTML 要素

ウェブの履歴全体を通じて、コンテンツを埋め込むために多くの HTML 要素が提案され、API が作成されてきました。以前は、複数の <frame> 要素と <frameset> 要素を使用してサイトを作成するのが一般的でした。複数の <frameset> 要素があるサイトでは、個々のフレームのソースに関係なく、親ページの URL がアドレスバーに表示されます。そのため、サイト内のコンテンツへのリンクを共有するのが困難でした。これらの API は非推奨になりました。

他のユースケースに対応するために、Java <applet> 要素などのプラグイン テクノロジーが使われていた時代もありました。これは後に <object> 要素に置き換えられました。この 2 つの要素は、Flash プラグインの表示によく使用されていましたが、(iframe に似た)他の HTML 要素の表示にも使用されていました。<canvas><audio><video><svg> などの他の要素では、<object> 要素と <applet> 要素の両方が古くなっています。

<object><embed> はまだ正式に非推奨ではありませんが、特に奇妙な動作があるため、使用を避けることをおすすめします。<applet> は 2017 年に HTML 仕様から削除されました

おわりに

既存の iframe 仕様を使用して、任意のウェブサイトにコンテンツを安全に埋め込むことができます。セキュリティとスタイルを改善するために、<fencedframe><portal> など、より多くの HTML 要素が提案されています。Google は、フェンス付きフレームの提案の進捗状況を引き続きお伝えします。

ヒーロー画像(作成者: Jackson So)。