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

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 ファイルや Service Worker など)を指します。

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

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

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

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

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