Chrome 拡張機能で eval を使用する

Chrome の拡張機能システムでは、かなり厳格なデフォルトのコンテンツ セキュリティ ポリシー(CSP)が適用されています。 ポリシーの制限は単純です。スクリプトは行外に配置し、 JavaScript ファイルとインライン イベント ハンドラは、addEventListener を使用するように変換する必要があります。eval() は、 無効です。Chrome アプリにはより厳格なポリシーがあり、Google はそのセキュリティにも満足しています プロパティを定義できます。

ただし、さまざまなライブラリで eval()eval に似た構造( new Function(): パフォーマンスの最適化と式の容易さ。テンプレート ライブラリは、 このような実装方法になりがちです一方(Angular.js など)は CSP をサポートしており、 多くの一般的なフレームワークは、Google Cloud と互換性のあるメカニズムにまだ更新できていません。 拡張機能evalの距離の短い世界。そのため、この機能のサポート終了は、 デベロッパーにとって予想以上に問題になります

このドキュメントでは、これらのライブラリをプロジェクトに含めるための安全なメカニズムとして、サンドボックス化について説明します。 セキュリティを損なうこともありません。簡潔にするために拡張機能という用語を使用していますが、 アプリケーションに等しく適用されます。

サンドボックスが重要な理由

eval は拡張機能の内部で危険です。実行するコードは、 高い権限の環境下で有効にします。以下を実現できる強力な chrome.* API が多数用意されています。 ユーザーのセキュリティとプライバシーに深刻な影響を与えるため。単純なデータの引き出しは最小限です 提供されているソリューションは、eval がどちらのコードにもアクセスせずにコードを実行できるようにするサンドボックスです。 拡張機能の高価値 API に対して行われます。データも API も、まったく問題ありません。

これは、拡張機能パッケージ内の特定の HTML ファイルをサンドボックス化してリストすることで実現しています。 サンドボックス化されたページが読み込まれると、一意のオリジンに移動され、拒否されます chrome.* API へのアクセス。このサンドボックス化されたページを iframe 経由で拡張機能に読み込むと、次のことができます。 Kubernetes にメッセージを渡し、そのメッセージに対してなんらかの方法で処理し、 表示されます。このシンプルなメッセージ メカニズムにより、eval ドリブンを安全に含めるために必要なすべての機能が提供されます。 ワークフロー内のコードを実行します

サンドボックスの作成と使用

コードをすぐに詳しく知りたい場合は、サンドボックスのサンプル拡張機能を入手し、 オフ。これは、Handlebars 上に構築された小さなメッセージング API の実例です。 使用するために必要なものがすべて揃っているはずです。新しい P-MAX キャンペーンを ここでそのサンプルを見ていきましょう

マニフェスト内のファイルを一覧表示する

サンドボックス内で実行する必要がある各ファイルは、拡張機能のマニフェストに sandbox プロパティ。これは重要なステップであり、忘れやすいため、 サンドボックス化されたファイルがマニフェストにリストされています。このサンプルでは、ファイルをサンドボックス化して、 「sandbox.html」という名前で作成されます。マニフェスト エントリは次のようになります。

{
  ...,
  "sandbox": {
     "pages": ["sandbox.html"]
  },
  ...
}

サンドボックス化されたファイルを読み込む

サンドボックス化されたファイルで何か面白いことを行うには、ファイルを 拡張機能のコードでアドレス指定できます。ここでは、sandbox.htmliframe を介して拡張機能のイベントページeventpage.html)にアクセスする。eventpage.js にコードが含まれます。 これは、iframe を見つけて、ブラウザ アクションがクリックされるたびにサンドボックスにメッセージを送信します。 ページ上で実行し、contentWindowpostMessage メソッドを実行します。メッセージはオブジェクトであり、 contextcommand の 2 つのプロパティを含む。後ほど、両方の方法について説明します。

chrome.browserAction.onClicked.addListener(function() {
 var iframe = document.getElementById('theFrame');
 var message = {
   command: 'render',
   context: {thing: 'world'}
 };
 iframe.contentWindow.postMessage(message, '*');
});
postMessage API に関する一般的な情報については、MDN に関する postMessage のドキュメント をご覧ください。かなり完全な内容なので、一読する価値があります。特に、データをやり取りできるのは、シリアル化可能な場合だけです。たとえば、関数はそうではありません。

危険なことをする

sandbox.html が読み込まれると、Handlebars ライブラリを読み込み、インライン 次のように Handlebars が提案する方法を使用します。

<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>Hello, !</h1>
  </div>
</script>
<script>
  var templates = [];
  var source = document.getElementById('hello-world-template').innerHTML;
  templates['hello'] = Handlebars.compile(source);
</script>

絶対に失敗することはありません。Handlebars.compile が最終的に new Function を使用しても、正常に動作する その結果、templates['hello'] にコンパイルされたテンプレートができあがります。

結果を返す

このテンプレートを使用できるように、コマンドを受け入れるメッセージ リスナーをセットアップします。 [イベント]ページから渡された command を使用して、実行する処理を決定します( レンダリング以外の処理も想像してくださいテンプレートの作成などが考えられます場合によっては、 渡され、context はレンダリングのためにテンプレートに直接渡されます。レンダリングされた HTML イベントページに返されるため、拡張機能は後でイベントページを使用して有用な処理を行うことができます。

<script>
  window.addEventListener('message', function(event) {
    var command = event.data.command;
    var name = event.data.name || 'hello';
    switch(command) {
      case 'render':
        event.source.postMessage({
          name: name,
          html: templates[name](event.data.context)
        }, event.origin);
        break;

      // case 'somethingElse':
      //   ...
    }
  });
</script>

[Event] ページに戻ると、このメッセージが表示され、html で興味深い処理が行われます 渡したデータを確認できます。ここでは、デスクトップ通知を介してエコー出力しますが、 この HTML を拡張機能の UI の一部として安全に使用できます。挿入方法 innerHTML は、サンドボックス化の完全な不正使用であっても、重大なセキュリティ リスクをもたらすことはありません。 危険なスクリプトやプラグインのコンテンツを挿入することは アクセスします。

このメカニズムによりテンプレートの作成は単純ですが、もちろんテンプレートに限定されません。制限なし 厳格なコンテンツ セキュリティ ポリシーですぐに利用できないコードは、サンドボックス化できます。 拡張機能のコンポーネントをサンドボックス化し、正常に実行される プログラムの各部分を、実行に必要な最小限の権限に制限します。 必要があります。Google 提供の安全なウェブアプリと Chrome 拡張機能の作成に関するプレゼンテーション I/O 2012 では、これらの手法の実例をいくつか紹介しています。 あります。