代表的な面接トピック

フロントエンド面接:ブラウザ拡張機能の最小権限パーミッションをどのように設計しますか?

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

質問

ツールバーのクリック後に現在のページを読み取り、管理されたAPIを呼び出すブラウザ拡張機能を構築しています。activeTab、optional_permissions、host_permissionsをいつ使用するか、そして拒否、失効、アップグレード、セキュリティ監査をどのように処理するかを説明しながら、そのManifest V3権限モデルを設計してください。

設問と適切なコンテキスト

この拡張機能は、明示的なツールバークリックの後にのみ現在のページを処理し、フィルタリングされたフィールドを管理されたバックエンドに送信します。すべてのタブのバックグラウンドスキャンや、任意のサイトのCookieへのアクセスは不要です。Manifest V3の権限分割、ランタイムフロー、グレースフルデグラデーション、およびリリース検証計画を提案してください。

この質問は、ブラウザ拡張機能の権限境界とプロダクトセキュリティをテストします。認証、データ最小化、監査コントロールは依然としてバックエンドが担当します。拡張機能の権限はこれらに代わるものではありません。

面接官が評価するポイント

面接官は、API機能、到達可能なホスト、およびユーザーの同意が別々の決定事項として扱われているかを確認したいと考えています。Chromeは、API権限、ホスト権限、オプションの権限、およびactiveTabを個別に文書化しています。これらは利用可能なAPI、URLアクセス、インストール時の警告、およびアップデートの挙動に影響を与えます。

優れた回答は、最小限の機能から始め、現在のページに対するワンショットのアクションで<all_urls>をリクエストすべきでない理由を説明し、拒否、失効、アップグレード、およびテレメトリをカバーします。単に「権限を追加する」と言うだけでは、安全なライフサイクルを示したことにはなりません。

最初に確認すべき明確化のための質問

  • 「現在のページ」には、特殊なページ、クロスオリジンフレーム、file URL、またはシークレットウィンドウが含まれますか?
  • APIには完全なドキュメントが必要ですか、それともユーザーが選択したフィールドのみが必要ですか?
  • ユーザーがクリックしていないときでも、拡張機能はページの変更を監視する必要がありますか?
  • どのWebExtensions実装をサポートする必要がありますか?
  • エンタープライズポリシーで権限を事前設定できますか?また、監査フィールドはどのくらいの期間保持できますか?

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

「私は機能を現在のページの読み取り、バックエンド通信、ストレージに分割します。ワンショットのアクションには、広範なホストアクセスの代わりにactiveTabを使用します。真に必要なクロススクリーンのバックグラウンド機能のみが、ユーザーがその機能をトリガーしたときにリクエストされる正確なoptional_host_permissionsを正当化します。必要なAPI権限のみを宣言し、拒否または失効時には処理を停止し、手動コピーのフォールバックを提供します。アップグレード前には権限の差分を確認し、新しいアクセスとデータフローを監視します。ロールバック時には新しい機能を削除します。」

ステップごとの詳細な回答

ステップ 1: 動作を権限にマッピングする

storagescriptingなどのAPI権限は拡張機能APIの機能を提供し、ホスト権限は対話可能なURL範囲を定義します。マニフェストは、後で必要になるかもしれない機能からではなく、個々のデータフローから導き出されるべきです。

ユーザーがクリックしたタブのみを処理するための出発点は次のとおりです。

json
{
  "manifest_version": 3,
  "permissions": ["activeTab", "scripting", "storage"],
  "optional_host_permissions": ["https://app.example.com/*"]
}

スクリプトが現在のページにのみ挿入される場合、activeTabはユーザーアクションの後に一時的なアクセスを許可します。タブを閉じるかナビゲーションを行うと終了します。製品がapp.example.comのために真にバックグラウンド処理を必要とする場合は、デフォルトで*://*/*にするのではなく、正確なオプションのホスト権限を評価します。

ステップ 2: プログレッシブコンセントを設計する

インストール時には、コアとなる低リスクの機能のみをリクエストします。ユーザーが「このページを分析」をクリックしたときに、URLを許可されたセットと照合します。追加のホストが必要な場合は、chrome.permissions.request()を呼び出し、目的、スコープ、および機能を終了する方法を説明します。

ts
const granted = await chrome.permissions.request({
  origins: ["https://app.example.com/*"]
});
if (!granted) {
  showManualCopyFallback();
  return;
}

成功はブラウザ機能が利用可能であることを意味しますが、バックエンド認証をバイパスするものではありません。リクエストが失敗した場合、ユーザーが後で失効させた場合、またはポリシーによって無効化された場合は、プロンプトを繰り返すことなく権限なしの状態に戻ります。

ステップ 3: アクティブ、付与済み、および失効可能な状態を区別する

Chromiumは、現在アクティブな権限と過去に付与された権限を区別します。chrome.permissions.remove()は現在の機能を減らしますが、過去の付与セットには権限が記録されたままになる場合があり、後のリクエストで同じプロンプトが再表示されないことがあります。ランタイムの決定は現在利用可能なものを使用する必要があり、設定には明確な失効アクションを公開する必要があります。

すべてのタスクの前に、実際の権限についてchrome.permissions.contains()を呼び出します。タスク中はpermissions.onRemovedをリッスンし、読み取りとアップロードを停止し、送信キューをクリアして、監査可能な権限変更イベントを記録します。

ステップ 4: 拒否、アップグレード、およびロールバックを処理する

拒否された場合は、手動選択、コピーアンドペースト、終了などの非技術的な次のステップを提示します。拒否をネットワークエラーとして分類したり、バックグラウンドで権限リクエストを再試行したりしないでください。

リリース前に、新しいAPI、ホストパターン、コンテンツスクリプトの一致、およびデータフィールドをカバーする権限の差分を作成します。Chromeは、アップデートによって権限が増加した場合に拡張機能を無効化し、新たな同意を待つことがあります。また、権限を削除しても過去の付与が必ずしも消去されるわけではないため、ロールバックテストでは、以前に権限を付与したユーザーと一度も付与しなかったユーザーの両方を対象にする必要があります。

ステップ 5: 権限をテスト可能なセキュリティ境界にする

コンテンツスクリプトはページによって制御される入力を処理するため、メッセージハンドラは送信者、メッセージタイプ、およびサイズを検証する必要があります。バックエンドは、拡張機能のID、ユーザーID、ターゲットリソース、およびフィールドの許可リストを再承認する必要があります。ホスト権限はブラウザの機能を制限するものであり、ページを信頼できるものにしたり、拡張機能が読み取ったデータを誤ったバックエンドに送信するのを防いだりするものではありません。

ローンチ前に、インストール、許可、拒否、失効、ナビゲーション後のactiveTabの期限切れ、オプションホストのリクエスト、権限が増加するアップデート、ロールバック、エンタープライズポリシーによる無効化、サポートされていないブラウザ、およびオフラインモードのマトリックスを作成します。テレメトリには、ページテキストではなく、権限キー、ホストパターン、結果、およびバージョンを記録する必要があります。

質の高い回答例

「私は機能とデータフローのマップから始めます。ツールバーアクションは現在のページのみを処理するため、コア設計では全サイトへのアクセスを持たせず、activeTabscripting、および必要なstorageを使用します。app.example.comのためのバックグラウンド機能のみが、ユーザーがトリガーしたときにリクエストされる正確なオプションのホスト権限を使用します。リクエストの前に目的とスコープを説明し、拒否後は手動選択を提供し、プロンプトのループを回避します。

各タスクの前に現在の権限を確認し、失効をリッスンします。アクセスが失われた場合は読み取りを停止し、送信キューをクリアし、バックエンドでIDとリソースを再承認させます。アップデートの前にはAPI、ホスト、コンテンツスクリプトの変更の差分を取り、無効化、新たな同意、ロールバックをテストします。最後に、権限マトリックスと匿名化されたテレメトリを使用して、バックグラウンドスキャンがないこと、クロスホストインジェクションがないこと、ログにページテキストが含まれないこと、および拒否や失効に対して安全に機能低下することを確認します。」

よくある間違い

  • デフォルトで<all_urls>をリクエストする → 読み取りとインジェクションの露出を拡大し、警告を増やす → activeTabから始め、継続的な機能に対して正確なホストを評価する。
  • optional_host_permissionsを自動的な同意として扱う → 宣言はユーザーの承認ではない → 機能実行時にリクエストし、拒否を処理する。
  • インストール時のみ権限を確認する → ユーザーは後で権限を取り消すことができる → 作業前に確認し、削除をリッスンする。
  • アップグレード時にコードの変更のみを確認する → 新しい権限によって拡張機能が無効化される可能性がある → 権限セットの差分を取り、過去の付与をテストする。
  • ブラウザの権限をバックエンドの認可として扱う → データが誤ったアカウントに送信される可能性がある → サーバー側でID、リソース、フィールドを再承認する。
  • 同意テキストをAPI名で埋め尽くす → ユーザーが有用なリスクモデルを形成できない → 目的、スコープ、終了方法を説明する。

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

フォローアップ 1: なぜ<all_urls>を直接リクエストしないのですか?

現在のページに対するワンショットのアクションでは、すべてのサイトへのバックグラウンドアクセスは不要です。activeTabはユーザーアクションの後に一時的な機能を付与し、長期的な露出を減らします。明確で継続的なクロススクリーンの要件のみが、正確なホストアクセスを正当化します。

フォローアップ 2: ユーザーがアクセスを取り消したときに、すでにアップロードされたデータはどうなりますか?

失効は以降のブラウザアクセスを防ぎますが、すでにデバイスを離れたデータを回収することはできません。バックエンドで最小限のフィールド、短い保持期間、削除コントロールを使用します。ローカルの送信キューをクリアし、どのような処理がすでに行われたかをユーザーに伝えます。

フォローアップ 3: オプションの権限が成功した後、なぜバックエンドで再承認を行うのですか?

ブラウザの権限は、拡張機能がページを読み取ることができることを示しているだけであり、ユーザーがビジネスリソースにアクセスできることを示すものではありません。バックエンドは、セッション、拡張機能のバージョン、ターゲットリソース、およびフィールド許可リストを検証し、古いリクエストや異常なリクエストを拒否する必要があります。

フォローアップ 4: ChromeとFirefoxの権限動作は同一であると想定できますか?

いいえ。WebExtensionsの概念は共有していますが、プロンプト、マッチパターン、ランタイムの境界が異なる場合があります。ターゲットブラウザごとにインストール、リクエスト、失効、ナビゲーション、アップグレードをテストし、その違いを互換性マトリックスに保持してください。

公開情報ソース

関連する質問