質問とスコープ
ダッシュボードはパブリック HTTPS オリジンから提供されます。プライベートアドレスにあるプリンターや localhost 上のヘルパーを呼び出すことがあり、ローカルネットワークに到達すべきではないベンダーの iframe も埋め込まれています。ブラウザがパブリック、ローカル、ループバックのアドレス空間をどのように区別するか、いつユーザーパーミッションが必要になるか、そして拒否された場合にページがどのように回復すべきかを説明してください。
アプリケーションの認可、CORS、およびデバイス認証は、別々のレイヤーとしてスコープ内に含めてください。ブラウザのパーミッションはユーザーの同意境界であり、プリンターが現在のアカウントに属していることの証明ではありません。ブラウザが Local Network Access を実装していない場合、プロダクトが手動設定パスを提供できるものと想定します。
面接官がテストしていること
重要な評価基準は、プライベートエンドポイントを呼び出すパブリックページをセキュリティ境界として認識しているかどうかです。優れた回答では、ルーターやプリンターに対する CSRF スタイルの攻撃に言及し、セキュアコンテキスト、アドレス空間の分類、パーミッション状態、および埋め込みコンテンツの許可リストによってフローを制約します。
面接官は、あなたが local-network と loopback-network を混同していないか、あるいは CORS プリフライトの成功によってアクセスが付与されると思い込んでいないかも探ります。良い回答では、ポリシー、パーミッション、混在コンテンツ、CORS、デバイス認証をそれぞれ独立したゲートとして扱います。
回答前に明確にすべき質問
- すべてのターゲットは事前に判明していますか、それともユーザーが任意の IP アドレスを入力できますか? 任意のスキャンには異なるプロダクト境界が必要であり、汎用的な「接続」ボタンの背後に隠すべきではありません。
- ヘルパーは
localhost上にのみ存在しますか、それともプライベートサブネット経由で到達可能ですか? これにより、ループバックまたはローカルネットワークのどちらのパーミッションが必要かが変わります。 - ベンダーの iframe やネストされたフレームがリクエストを実行することはありますか? ある場合、すべてのフレーム境界で機能とその遷移先オリジンの可能性を明示的に委譲する必要があります。
- どのブラウザとエンタープライズポリシーがサポートされていますか? ロールアウトのタイミングが異なるため、セキュリティを暗黙的に弱めるのではなく、互換性パスを観測可能にする必要があります。
30秒の回答フレームワーク
「ダッシュボードを HTTPS で維持し、各接続先をパブリック、ローカル、またはループバックとして分類し、必要な場合にのみ対応するブラウザパーミッションを要求します。レスポンスポリシーではベンダーの iframe へのローカルアクセスを拒否し、iframe の接続が必要な場合は、その allow リストで正確なオリジンとすべての遷移ターゲットを指定します。アクションの前にパーミッション状態を確認し、アクセスが必要な理由を表示し、混在コンテンツと CORS の失敗を個別に処理し、未サポートのブラウザには手動設定パスを提供します。テストでは、任意のホストや本番環境の広告フレームがローカルネットワークリクエストをトリガーしないことを検証します。」
ステップバイステップの詳細な回答
ステップ 1: 信頼境界とアドレス空間を定義する
パブリック Web サイトが、ユーザーのルーター、プリンター、または開発サービスに対して状態を変更するリクエストを暗黙的に送信してはなりません。3 つの接続先クラスをモデル化します。パブリックアドレスはグローバルに到達可能であり、ローカルアドレスはユーザーのネットワーク上でのみ到達可能であり、ループバックアドレスは同一デバイスをターゲットとします。localhost はすべてのプライベートサブネットと同等ではありません。
リクエストの棚卸しには、fetch、サブリソースの読み込み、WebSocket、WebTransport、WebRTC、Service Worker のリクエスト、およびフレーム遷移を含める必要があります。ソケットを開くライブラリは、アプリケーションコードに直接の fetch 呼び出しが含まれていない場合でも、同じ境界を越える可能性があります。
ステップ 2: セキュアコンテキストと明示的なパーミッションを必須にする
HTTPS のトップレベルページを使用します。サポートされているブラウザでは、デバイスアクションを試みる前に関連するパーミッションを照会します。
const localState = await navigator.permissions.query({ name: "local-network" });
const loopbackState = await navigator.permissions.query({ name: "loopback-network" });granted、prompt、denied をプロダクト状態として扱います。プロンプトを表示する前に目的を説明し、拒否された場合はループで再試行するのではなく、修復リンクまたは手動設定を表示します。ターゲットが偶発的に応答した場合であっても、HTTP ページはこのフローでサポートされていないとみなす必要があります。
ステップ 3: 埋め込みドキュメントを制約する
トップレベルのレスポンスは、それを必要とする機能とオリジンのみを委譲できます。ベンダーフレームにはローカルネットワーク機能を付与しません。
Permissions-Policy: local-network=(self "https://dashboard.example"), loopback-network=(self "https://dashboard.example")信頼できるセットアップフレームが接続する必要がある場合は、限定的に委譲します。
<iframe src="https://setup.example" allow="local-network https://setup.example; loopback-network https://setup.example"></iframe>ヘッダーと iframe ポリシーは交差(論理積)します。フレームが親の拒否設定を広げることはできません。フレームがローカルリクエストも行う別のオリジンに遷移する場合、そのオリジンを明示的にリストするか、遷移後にアクセスを拒否します。ネストされたフレームでは、すべての境界でポリシーが必要です。
ステップ 4: パーミッションを混在コンテンツおよび CORS から分離する
パーミッションを取得しても、安全でないリクエストが普遍的に有効になるわけではありません。一部のブラウザ実装では同意後に特定のローカル HTTP エンドポイントを許可しますが、その他の混在コンテンツチェックは引き続き適用されます。リクエストのターゲットアドレス空間メタデータは、ブラウザとエンドポイントのコントラクトがサポートしている場合にのみ使用し、パブリックな接続先をバイパスするために使用しないでください。
CORS は、ターゲットが Web オリジンに対してレスポンスの読み取りを許可するかどうかを答えるものです。パブリックページがプリンターに到達することを認可するものではなく、デバイス認証を代替することはできません。状態を変更するコマンドの場合は、デバイス固有のチャレンジまたはペアリングコードを使用し、コマンドを冪等にします。
ステップ 5: フォールバックとテレメトリを設計する
サポートされていないブラウザでは、手動 IP、ネイティブヘルパー、またはユーザー誘導によるペアリングルートを公開する必要があります。認証情報や未加工のローカルレスポンスをログに記録することなく、接続先クラス、パーミッション状態、ポリシー結果、ブラウザ機能、CORS 結果、およびデバイス認証結果を記録します。リリースによって新しいホストクラスがローカルアクセスを要求した場合や、広告フレームがそれを試みた場合、本番アラームを発火させる必要があります。
ステップ 6: ネガティブマトリックスをテストする
localhost、プライベート IP、パブリックに解決されるパブリックホスト名、ローカルに解決されるパブリックホスト名、HTTP ページ、欠落したパーミッション、拒否されたパーミッション、iframe 委譲の欠落、ネストされたフレーム、リストにないオリジンへの遷移、ブロックされた CORS レスポンス、デバイス認証の失敗、および DNS 解決中にクラスが変更されるアドレスをテストします。意図したユーザーアクションのみがプロンプトをトリガーできること、およびバックグラウンドの再試行が範囲をスキャンしないことを検証します。
高品質な回答例
「パブリックからローカルへのリクエストは、要求およびスコープ設定が必要な機能(capability)として扱います。ダッシュボードは HTTPS のままとし、プリンターとヘルパーの接続先を別々に分類し、local-network または loopback-network の状態を確認し、1 回の制限されたリクエストを行う前にプロンプトについて説明します。レスポンスポリシーは、ベンダーの iframe に対して両方の機能を拒否します。信頼できるセットアップ iframe が必要な場合、その allow リストにはセットアップオリジンと、遷移する可能性のあるすべてのオリジンのみを含めます。
ブラウザのパーミッション、混在コンテンツチェック、CORS、およびデバイス認証を別々のゲートとして維持します。拒否されたブラウザや未サポートのブラウザでは、リクエストを繰り返す代わりに手動ペアリングを行います。テストでは、ローカル、ループバック、パブリック、DNS 再分類、ネストされたフレーム、委譲の欠落、拒否されたパーミッション、CORS 失敗、デバイス認証失敗をカバーします。広告や任意のホストがリクエストまたはプロンプトをトリガーできる場合、リリースを停止します。」
よくある間違い
- すべてのプライベート IP をループバックとして扱う → ループバックとローカルネットワークではパーミッションセマンティクスが異なります → パーミッションを選択する前に接続先を分類します。
- プロンプトが表示されるまで拒否後に再試行する → これにより予期しない動作やスキャンのような挙動が発生します → コンテキストを 1 回表示し、修正手順を提供します。
- CORS によりプリンターが信頼できるとみなす → CORS はレスポンスの共有を制御するものであり、デバイスの身元を制御するものではありません → デバイスをペアリングし、コマンドを認証します。
- ベンダーフレームに
local-network *を付与する → リダイレクトやネストされたドキュメントによって信頼セットが拡大する可能性があります → 正確なオリジンをリストするか、委譲を拒否します。 - localhost のみのテストに依存する → パブリックからローカルへの境界を検証できない可能性があります → パブリック HTTPS オリジンから各アドレスクラスに対してテストします。
フォローアップの質問と回答
フォローアップ 1: なぜ localhost は開発環境で動作したのに、本番環境で失敗したのですか?
開発環境はループバックオリジンまたは新しい制限のないブラウザから実行されている可能性があります。本番環境はループバックまたはローカル空間に越境するパブリックオリジンであるため、セキュアコンテキスト、パーミッション、ポリシー、混在コンテンツ、および CORS ゲートがすべて関係してきます。パブリック HTTPS テストオリジンから再現してください。
フォローアップ 2: iframe はトップレベルのパーミッションを自動的に継承できますか?
ポリシーと委譲ルール内でのみ継承されます。クロスオリジンフレームには明示的な機能付与が必要であり、ネストされたフレームには独自の委譲が必要です。ユーザーの決定は埋め込みコンテキストに関連付けられますが、欠落した allow やリストにない遷移先オリジンをバイパスすることはありません。
フォローアップ 3: agent.example の DNS がパブリックからプライベートに変更された場合はどうなりますか?
解決されたアドレスを再分類し、適切なパーミッションとセキュアコンテキストパスを要求します。パブリックの分類を永続的にキャッシュしないでください。分類の移行をログに記録し、接続先がプロダクトの承認済みターゲットセットにない場合はフェイルクローズ(安全側に倒して拒否)します。
フォローアップ 4: なぜプリンターコマンドに対してパーミッションプロンプトだけでは不十分なのですか?
プロンプトは、ユーザーがサイトからのネットワークアクセスを許可したことを示すのみであり、デバイスの認証や要求された操作の認可を行うものではありません。デバイスをペアリングし、コマンドをアカウントおよびノンスにバインドし、再試行を冪等にしてください。