拡張機能のセキュリティを強化

Manifest V3 でのセキュリティの強化

これは、拡張機能 Service Worker の一部ではないコードに必要な変更について説明する 3 つのセクションの最後です。拡張機能のセキュリティを強化するために必要な変更について説明します。残りの 2 つのセクションでは、Manifest V3 へのアップグレードに必要なコードの更新と、ブロックするウェブ リクエストの置き換えについて説明します。

任意の文字列の実行を削除

executeScript()eval()new Function() を使用して外部ロジックを実行することはできなくなりました。

  • すべての外部コード(JS、Wasm、CSS)を拡張機能バンドルに移動します。
  • スクリプトとスタイルの参照を更新して、拡張機能バンドルからリソースを読み込みます。
  • chrome.runtime.getURL() を使用して、実行時にリソース URL をビルドします。
  • サンドボックス化された iframe を使用する: evalnew Function(...) は、サンドボックス化された iframe で引き続きサポートされます。詳しくは、サンドボックス化された iframe に関するガイドをご覧ください。

executeScript() メソッドは、tabs 名前空間ではなく scripting 名前空間にあります。呼び出しの更新については、executeScript() を移動するをご覧ください。

任意の文字列の実行が可能な特殊なケースがいくつかあります。

リモートでホストされているコードを削除

Manifest V3 では、拡張機能のすべてのロジックが拡張機能パッケージの一部である必要があります。Chrome ウェブストアのポリシーに準拠するため、リモートでホストされているファイルを読み込んで実行することはできなくなります。次に例を示します。

  • デベロッパーのサーバーから取得された JavaScript ファイル。
  • CDN でホストされているライブラリ。
  • リモート ホスト型コードを動的に取得するバンドルされたサードパーティ ライブラリ。

ユースケースとリモート ホスティングの理由に応じて、代替アプローチを利用できます。このセクションでは、検討すべきアプローチについて説明します。リモートでホストされているコードの処理で問題が発生した場合は、こちらのガイダンスをご覧ください。

構成ドリブンの機能とロジック

拡張機能は、実行時にリモート構成(JSON ファイルなど)を読み込んでキャッシュに保存します。キャッシュに保存された構成によって、有効になる機能が決まります。

リモート サービスによる外部化されたロジック

拡張機能がリモート ウェブサービスを呼び出す。これにより、コードを非公開のまま必要に応じて変更でき、Chrome ウェブストアに再送信する余分なオーバーヘッドを回避できます。

サンドボックス化された iframe にリモートでホストされるコードを埋め込む

リモートでホストされるコードは、サンドボックス化された iframe でサポートされています。この方法は、コードが埋め込みページの DOM へのアクセスを必要とする場合には機能しません。

サードパーティ ライブラリをバンドルする

以前に外部サーバーから読み込んでいた React や Bootstrap などの一般的なフレームワークを使用している場合は、縮小化されたファイルをダウンロードしてプロジェクトに追加し、ローカルでインポートできます。次に例を示します。

<script src="./react-dom.production.min.js"></script>
<link href="./bootstrap.min.css" rel="stylesheet">

ライブラリを Service Worker に含めるには、マニフェストで "background.type" キー"module" に設定し、import ステートメントを使用します。

タブ挿入スクリプトで外部ライブラリを使用する

scripting.executeScript() を呼び出すときに files 配列に追加することで、実行時に外部ライブラリを読み込むこともできます。実行時にリモートでデータを読み込むことはできます。

chrome.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['jquery-min.js', 'content-script.js']
});

関数を挿入する

より動的な処理が必要な場合は、scripting.executeScript() の新しい func プロパティを使用すると、関数をコンテンツ スクリプトとして挿入し、args プロパティを使用して変数を渡すことができます。

Manifest V2
let name = 'World!';
chrome.tabs.executeScript({
  code: `alert('Hello, ${name}!')`
});

バックグラウンド スクリプト ファイル内。

Manifest V3
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();

function showAlert(givenName) {
  alert(`Hello, ${givenName}`);
}

let name = 'World';
chrome.scripting.executeScript({
  target: {tabId: tab.id},
  func: showAlert,
  args: [name],
});

バックグラウンド Service Worker。

Chrome 拡張機能のサンプル リポジトリには、ステップ実行可能な関数インジェクションの例が含まれています。getCurrentTab() の例は、その関数のリファレンスにあります。

他の回避策を探す

上記の方法でユースケースに対応できない場合は、代替ソリューションを見つける(別のライブラリに移行するなど)か、ライブラリの機能を別の方法で使用する必要があります。たとえば、Google アナリティクスの場合は、Google アナリティクス 4 のガイドで説明されているように、公式のホスト型 JavaScript バージョンを使用する代わりに、Google Measurement Protocol に切り替えることができます。

コンテンツ セキュリティ ポリシーを更新する

"content_security_policy"manifest.json ファイルから削除されていませんが、"extension_pages""sandbox" の 2 つのプロパティをサポートする辞書になりました。

Manifest V2
{
  ...
  "content_security_policy": "default-src 'self'"
  ...
}
Manifest V3
{
  ...
  "content_security_policy": {
    "extension_pages": "default-src 'self'",
    "sandbox": "..."
  }
  ...
}

extension_pages: 拡張機能のコンテキスト(HTML ファイルやサービス ワーカーなど)を指します。

sandbox: 拡張機能で使用するサンドボックス化された拡張機能ページを指します。

サポートされていないコンテンツ セキュリティ ポリシーを削除する

Manifest V3 では、Manifest V2 で許可されていた "extension_pages" フィールドの特定のコンテンツ セキュリティ ポリシー値が許可されなくなりました。具体的には、Manifest V3 ではリモートコード実行を可能にするものは禁止されています。script-src,object-srcworker-src ディレクティブには、次の値のみを指定できます。

  • self
  • none
  • wasm-unsafe-eval
  • パッケージ化されていない拡張機能のみ: localhost の送信元(http://localhosthttp://127.0.0.1、またはこれらのドメインの任意のポート)

sandbox のコンテンツ セキュリティ ポリシー値には、このような新しい制限はありません。