代表的な面接トピック

フロントエンド面接:埋め込み機能に対する安全な Permissions Policy をどのように設計しますか?

フロントエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

ダッシュボード上に信頼できる動画 iframe とミーティング iframe を埋め込み、同じページ上で信頼できない広告を配信しています。ミーティングのオリジンのみがマイクとカメラを使用でき、動画が全画面表示を使用でき、広告にはそれらの機能が一切付与されないように HTTP Permissions-Policy ヘッダーと iframe の allow 属性を設計してください。委任(delegation)、機能検出、失敗時の処理、およびロールアウト時のテストについて説明してください。

質問とスコープ

通話用の meet.example、再生用の video.example、および複数の広告フレームを埋め込んでいるダッシュボードを管理しているとします。ミーティングフレームには microphonecamera が必要であり、動画フレームには fullscreen が必要です。広告にはこれらの機能は一切不要です。ページは HTTPS であり、フレームのオリジンは既知で、ポリシーで許可されている場合でもブラウザはメディアの使用許可をユーザーに求める必要があります。

スコープは、ブラウザ側でのポリシー構成と診断です。認証、CSP、およびサーバー側の認可は個別の制御として扱います。レスポンスヘッダーはダッシュボードサーバーによって設定され、すべてのクロスオリジンフレームには明示的な allow 属性が付与されているものとします。

面接官がテストしていること

面接官は、レスポンスポリシー、フレームの委任、およびユーザーのランタイム権限という3つのゲートを区別できているかを確認しています。ヘッダーの許可リストだけではクロスオリジンフレームへのアクセスは許可されず、allow 属性によってその機能を拒否しているヘッダーの制限を広げることはできません。

また、利便性のためにワイルドカードを安易に使わないかもテストされます。優れた回答は、機密性の高い機能に対して () から開始し、正確なオリジンを指定し、ネストされたナビゲーションを処理し、API が利用できない場合に UI がどう動作するかを説明します。不十分な回答は * を記述し、許可プロンプトを待つだけで、その機能が安全であると判断してしまいます。

回答前に明確にすべき質問

  • ミーティングフレームおよび動画フレームは、どの正確なオリジンにナビゲートする可能性がありますか?異なるオリジンへのナビゲーションが発生する場合、フレームポリシーにその移動先を含める必要があるか、あるいはナビゲーション後に機能を拒否する必要があります。
  • ミーティングフレームはネストされたフレームを開きますか?その場合、委任を継続してよいかを定義し、最初のフレームの許可が永続的に継承されると仮定せずに、ネストされたオリジンをテストします。
  • どのブラウザや組み込み WebView がサポートされていますか?ポリシーの構文が正しくても、古いランタイムでは異なる障害の現れ方をすることがあります。
  • カメラやマイクの通話は必須ですか?オプションである場合、ポリシーまたはユーザーの権限が拒否された際に、UI でテキストのみのルートを提供できます。

30秒の回答フレームワーク

「カメラとマイクをデフォルトで () に設定し、レスポンスポリシーでミーティングのオリジンのみに付与します。全画面表示は動画のオリジンのみに付与します。ヘッダーとフレームポリシーの双方が必要となるため、各クロスオリジン iframe はその allow 属性で対象の機能を再度指定します。フレーム側では、ポリシーによる拒否をユーザーによる拒否と区別して検出し、フォールバックを描画します。権限プロンプトを認可として扱うことはしません。ロールアウト前には、同一オリジン、クロスオリジン、ナビゲーション、ネストされたフレーム、ヘッダー欠落、およびブラウザのフォールバックケースをテストします。」

ステップバイステップの詳細な回答

ステップ 1: デフォルト拒否のインベントリから始める

ページで使用されるポリシー制御対象のすべての機能と、それを所有するオリジンをリストアップします。「meeting」という製品名から権限を推測してはいけません。カメラとマイクは2つの独立した機能です。全画面表示はまた別の機能です。広告は明示的にゼロアクセスのクラスとします。

次のような明示的なヘッダーを使用します:

http
Permissions-Policy: camera=(self "https://meet.example"), microphone=(self "https://meet.example"), fullscreen=(self "https://video.example")

正確なオリジンリストにより、無関係なフレームに許可が与えられるのを防ぎます。ダッシュボード自体が機能にアクセスしてはならない場合は、self を削除して必要なフレームのオリジンのみに付与し、親ポリシーが委任を許可していることを確認します。

ステップ 2: 各 iframe の境界で委任する

ミーティングフレームはその2つの機能のみを受け取り、動画フレームは全画面表示のみを受け取ります:

html
<iframe src="https://meet.example/room" allow="camera; microphone"></iframe>
<iframe src="https://video.example/player" allow="fullscreen"></iframe>
<iframe src="https://ad.example/slot" allow=""></iframe>

クロスオリジンフレームの場合、レスポンスヘッダーにオリジンが記載されていても、allow を省略すると機能がブロックされます。逆に、広告に allow="camera" を追加しても、camera=() やヘッダーに存在しないオリジンを上書きすることはできません。

ステップ 3: ポリシーとユーザーの同意を異なる状態として扱う

Permissions-Policy は、ドキュメントが機能を使用できるかどうかを決定します。Permissions API とメディアプロンプトは、ユーザーによって付与された権限を表します。ブロックされた機能は、プロンプトが表示される前に失敗することがあります。フレームは、「ポリシー拒否」、「ユーザー拒否」、「非サポート」、「デバイスビジー」を別々のテレメトリおよび復旧テキストにマッピングする必要があります。

クライアント側のチェックをセキュリティ境界にしてはいけません。埋め込み元のページが委任を制御し、アプリケーションはサーバー側で通話を認証し、ルームのメンバーシップを認可します。

ステップ 4: ナビゲーションとネストされたフレームを明示的に処理する

ミーティングフレームがサポートオリジンにナビゲートできる場合、信頼されており同じ機能を必要とする場合にのみ、その移動先を allow ポリシーに含めます。フレームの最初の src オリジンと後からのナビゲーション先オリジンは同一視できません。ネストされたフレームについては、すべての境界で有効なポリシーを検証し、所有権が不明確な場合はデフォルトで拒否します。

ステップ 5: 観測可能なテストを実施してロールアウトする

プラットフォームで許可されている場合は、レポート専用の診断または小規模なルートコホートでヘッダーを配信し、ポリシー違反、プロンプトの結果、通話完了率、およびフォールバックの使用状況を比較します。同一オリジンフレーム、許可されたクロスオリジンフレーム、記載されていないクロスオリジンフレーム、欠落した allow 属性、変更されたサブドメイン、およびフレームのナビゲーションをテストします。広告でプロンプトが決して表示されないこと、および拒否されたミーティングフレームでテキストチャットが提供されることをアサートします。

質の高い回答例

「脅威モデルに基づいてポリシーを作成します。カメラとマイクは空の権限から開始し、ヘッダーには meet.example のみをリストします。全画面表示には video.example のみをリストします。2つのクロスオリジンフレームには一致する allow 属性を設定し、広告フレームには何も設定しません。ブラウザが依然としてユーザーの同意を制御するため、ミーティングコードはポリシーによるブロックをユーザーによる拒否と区別し、テキストのみのフォールバックを提供します。このヘッダーに認可ロジックを含めることはせず、サーバー側で引き続きルームとユーザーのチェックを行います。

グローバルに有効化する前に、許可されたオリジンと記載のないオリジン、同一サイトだがクロスオリジンとなるサブドメイン、allow の省略、フレームのナビゲーション、ネストされたフレーム、非サポートブラウザ、およびヘッダーの欠落というマトリックスを検証します。テレメトリは、メディアを録音・録画することなく、機能、フレームオリジン、ポリシー結果、ユーザー結果、およびフォールバックを記録します。広告から予期しないプロンプトが発生した場合や、信頼できないオリジンへのナビゲーション後にアクセスが成功した場合は、ロールアウトを停止します。」

よくある間違い

  • カメラとマイクに * を使用する → 対象となる任意のフレームが強力な機能を要求できてしまう → () から開始し、正確なオリジンを追加する。
  • HTTP ヘッダーのみを追加する → クロスオリジン iframe には依然としてコンテナの委任が必要である → 一致する allow 属性を設定する。
  • allow のみを追加する → フレーム側で親ポリシーを拡張することはできない → レスポンスとすべてのフレーム境界の両方を確認する。
  • プロンプトが表示されないことをブラウザのバグとして扱う → ポリシーによる拒否はユーザーの同意前に発生する可能性がある → ポリシー、同意、サポート状況、デバイスの状態を別々に報告する。
  • サブドメインを同一オリジンと見なす → Same-site(同一サイト)は Same-origin(同一オリジン)を意味しない → 各オリジンをリストアップし、ナビゲーションをテストする。

フォローアップの質問と回答

フォローアップ 1: ヘッダーにミーティングのオリジンが記載されているのに、機能がブロックされるのはなぜですか?

iframe の allow 属性、正確なスキームとポート、およびフレームがナビゲートしたかどうかを確認してください。クロスオリジンフレームの場合、ヘッダーの許可リストとコンテナポリシーの積集合(intersection)が適用されます。どちらか一方の許可が欠けていると、機能はブロックされます。

フォローアップ 2: ヘッダーを省略して allow に頼るべきですか?

いいえ。明示的なレスポンスポリシーにより、ページ所有者にトップレベルの境界が提供され、新しいフレームが追加された際の偶発的な許可を防ぐことができます。ヘッダーを省略すると、一部の機能に対して寛容なデフォルト設定が適用されたままになり、後からサードパーティを埋め込んだ際にポリシーのリグレッションが発生する可能性があります。

フォローアップ 3: ミーティングフレームがサポートドメインにナビゲートした場合、何が変わりますか?

移動先を新しいオリジンとして再評価します。信頼性、認証、およびデータ処理が確認された後にのみ、そのオリジンにカメラやマイクを許可してください。それ以外の場合は、ナビゲーションによってこれらの権限が失われるようにし、UI でフォールバックを説明する必要があります。

フォローアップ 4: Permissions Policy はサーバー側の認可を代替できますか?

いいえ。ドキュメント内でのブラウザ機能の可用性を制御するだけです。ユーザーの身元、ルームのメンバーシップ、またはリクエストが通話に参加できるかどうかを証明するものではありません。これらのチェックはサーバー側で維持し、ポリシーはブラウザにおける最小権限の境界として扱ってください。

公開情報ソース

関連する質問