script-src 'self'; object-src 'self'; worker-src 'self'
このポリシーでは、次の 3 つの方法で拡張機能とアプリケーションを制限することでセキュリティが追加されます。
次のようなコードは機能しません。
alert(eval("foo.bar.baz"));
window.setTimeout("alert('hi')", 10);
window.setInterval("alert('hi')", 10);
new Function("return foo.bar.baz");
このような JavaScript の文字列の評価は、一般的な XSS 攻撃ベクトルです。 代わりに、次のようなコードを記述する必要があります。
alert(foo && foo.bar && foo.bar.baz);
window.setTimeout(function() { alert('hi'); }, 10);
window.setInterval(function() { alert('hi'); }, 10);
function() { return foo && foo.bar && foo.bar.baz };
インライン JavaScript が実行されない
インライン JavaScript は実行されません。 この制限では、インライン ブロックとインライン <script>
イベント ハンドラー (など <button onclick="...">
) の両方が禁止されます。
最初の制限は、悪意のあるサード パーティによって提供されたスクリプトを誤って実行できないようにすることで、クロスサイト スクリプティング攻撃の巨大なクラスを一掃します。 ただし、コンテンツと動作をクリーン分離してコードを記述する必要があります。 たとえば、これを明確にする場合があります。 ブラウザー アクション ポップアップは、次の内容を含む 1 つとして pop-up.html
記述できます。
<!doctype html>
<html>
<head>
<title>My Awesome Pop-up!</title>
<script>
function awesome() {
// do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function clickHandler(element) {
setTimeout("awesome(); totallyAwesome()", 1000);
}
function main() {
// Initialization work goes here.
}
</script>
</head>
<body onload="main();">
<button onclick="clickHandler(this)">
Click for awesomeness!
</button>
</body>
</html>
ただし、この作業を想定した方法で行うには、次の 3 つのことを変更する必要があります。
定義は clickHandler
外部 JavaScript ファイルに移動する必要があります (popup.js
適切なターゲットである可能性があります)。
インライン イベント ハンドラー定義は、 の観点 addEventListener
から書き換え、 に popup.js
抽出する必要があります。 のような<body onload="main();">
コードを使用して現在プログラムを開始している場合は、要件に応じて、ドキュメントのイベントまたはload
ウィンドウのイベントにDOMContentLoaded
フックして置き換えることを検討してください。 一般に、より迅速にトリガーされるため、前者を使用します。
setTimeout
実行のために文字列"awesome(); totallyAwesome()"
を JavaScript に変換しないように、呼び出しを書き換える必要があります。
これらの変更は、次のようになります。
function awesome() {
// Do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function awesomeTask() {
awesome();
totallyAwesome();
}
function clickHandler(e) {
setTimeout(awesomeTask, 1000);
}
function main() {
// Initialization work goes here.
}
// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', clickHandler);
main();
});
<!doctype html>
<html>
<head>
<title>My Awesome Pop-up!</title>
<script src="popup.js"></script>
</head>
<body>
<button>Click for awesomeness!</button>
</body>
</html>
ローカル スクリプトとオブジェクト リソースのみが読み込まれます
スクリプトリソースとオブジェクト リソースは拡張機能パッケージからのみ読み込むことができます。Web から読み込むことはできません。 これにより、拡張機能で明示的に承認されたコードのみが実行され、アクティブなネットワーク攻撃者がリソースの要求を悪意を持ってリダイレクトすることを防ぐことができます。
外部 CDN からの jQuery (またはその他のライブラリ) の読み込みに依存するコードを記述する代わりに、拡張機能パッケージに特定のバージョンの jQuery を含めることを検討してください。 つまり、次の代わりに、
<!doctype html>
<html>
<head>
<title>My Awesome Pop-up!</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<button>Click for awesomeness!</button>
</body>
</html>
代わりに、次の方法を使用します。 ファイルをダウンロードし、パッケージに含め、次のように書き込みます。
<!doctype html>
<html>
<head>
<title>My Awesome Pop-up!</title>
<script src="jquery.min.js"></script>
</head>
<body>
<button>Click for awesomeness!</button>
</body>
</html>
既定のポリシーを緩和する
インライン スクリプト
インライン スクリプトは、ポリシーでソース コードの base64 でエンコードされたハッシュを指定することで許可できます。 このハッシュには、使用されるハッシュ アルゴリズム (sha256、sha384、または sha512) のプレフィックスを付ける必要があります。 例については、「スクリプト>要素の W3C > ハッシュ使用法」を<参照してください。
リモート スクリプト
一部の外部 JavaScript またはオブジェクト リソースが必要な場合は、スクリプトを受け入れる必要がある安全な配信元を許可することで、ポリシーを制限された範囲で緩和できます。 拡張機能の昇格されたアクセス許可で読み込まれたランタイム リソースが、想定どおりのリソースであり、アクティブなネットワーク攻撃者に置き換えられていないことを確認します。
中間者攻撃は、HTTP に対する単純な攻撃と検出不能の両方であるため、これらの配信元は受け入れられません。
現時点では、次のスキームを持つ許可リストの配信元を指定できます。 blob
filesystem
https
extension
および スキームには、配信元のホスト部分をhttps
extension
明示的に指定する必要があります。 https: https://*
https://*.com
、 などの汎用ワイルドカードは使用できません。サブドメイン ワイルドカードは https://*.example.com
許可されます。
パブリック サフィックスの一覧のドメインは、汎用の最上位ドメインとしても表示されます。 これらのドメインからリソースを読み込むには、サブドメインを明示的に一覧表示する必要があります。 たとえば、 https://*.cloudfront.net
は無効ですがhttps://XXXX.cloudfront.net
https://*.XXXX.cloudfront.net
、 には を指定allowlisted
できます。
開発を容易にするために、ローカル コンピューター上のサーバーから HTTP 経由で読み込まれるリソースは になります allowlisted
。 または のいずれかのポートで、許可リスト スクリプトとオブジェクト ソースhttp://127.0.0.1
http://localhost
を使用できます。
注意
HTTP 経由で読み込まれたリソースに対する制限は、直接実行されるリソースにのみ適用されます。 たとえば、任意の配信元への接続を作成 XMLHTTPRequest
する場合など、引き続き無料です。既定のポリシーでは、その他の CSP ディレクティブは制限されません connect-src
。
スクリプト リソースを HTTPS 経由で example.com
読み込むための緩和されたポリシー定義は、次のようになります。
"content_security_policy": "script-src 'self' https://example.com; object-src 'self'"
注意
と object-src
の両方script-src
がポリシーによって定義されます。 Microsoft Edge では、これらの各値を (少なくとも) ''self
に制限しないポリシーは受け入れられません。
評価された JavaScript
に対するeval()
ポリシーと関連する関数 (、setInterval(String)
、 new Function(String)
などsetTimeout(String)
) は、ポリシーに追加unsafe-eval
することで緩和できます。
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
ただし、ポリシーの緩和は避ける必要があります。 これらの種類の関数は、悪名高い XSS 攻撃ベクトルです。
既定のポリシーを引き締める
このポリシーは、利便性を犠牲にして、セキュリティを強化するために、拡張機能で許可されている範囲を問わず厳格化できます。 拡張機能で、関連付けられている拡張機能パッケージから任意の種類 (イメージなど) のリソースのみを読み込みることができるように指定するには、 の default-src 'self'
ポリシーが適切な場合があります。
コンテンツ スクリプト
説明するポリシーは、拡張機能のバックグラウンド ページとイベント ページに適用されます。 拡張機能のコンテンツ スクリプトにコンテンツ スクリプトを適用する方法は、より複雑です。
一般に、コンテンツ スクリプトは拡張機能の CSP の対象ではありません。 コンテンツ スクリプトは HTML ではないため、このメインの影響は、拡張機能の CSP で が指定unsafe-eval
されていない場合でも使用eval
できますが、これは推奨されません。 さらに、ページの CSP はコンテンツ スクリプトには適用されません。 より複雑なタグは、 <script>
コンテンツ スクリプトによって作成され、実行されているページの DOM に配置されます。 これらは、今後 DOM 挿入スクリプトとして参照されます。
DOM によって挿入されたスクリプトは、予期したとおりにページに挿入された直後に実行されます。 簡単な例として、次のコードを含むコンテンツ スクリプトを想像してください。
document.write("<script>alert(1);</script>");
このコンテンツ スクリプトでは、 の直後に が alert
発生します document.write()
。 これは、ページが指定するポリシーに関係なく実行されることに注意してください。 ただし、DOM が挿入したスクリプト内と、挿入時にすぐに実行されないスクリプトの両方で、動作がより複雑になります。
拡張機能が、 を指定する関連付けられた CSP を提供するページで実行されていることを想像してください script-src 'self'
。 次に、コンテンツ スクリプトで次のコードが実行されるとします。
document.write("<button onclick='alert(1);'>click me</button>'");
ユーザーがそのボタンをクリックした場合、 onclick
スクリプトは実行されません。 これは、スクリプトがすぐに実行されず、イベントが発生するまで click
解釈されないコードはコンテンツ スクリプトの一部とは見なされないため、ページの CSP (拡張機能ではなく) によって動作が制限されるためです。 また、その CSP では を指定 unsafe-inline
していないため、インライン イベント ハンドラーはブロックされます。
この場合、目的の動作を実装する正しい方法は、次のように、コンテンツ スクリプトからハンドラーを関数として追加 onclick
することです。
document.write("<button id='mybutton'>click me</button>'");
var button = document.getElementById('mybutton');
button.onclick = function() {
alert(1);
};
コンテンツ スクリプトで次を実行すると、もう 1 つの同様の問題が発生します。
var script = document.createElement('script');
script.innerHTML = 'alert(1);'
document.getElementById('body').appendChild(script);
この場合、スクリプトが実行され、アラートが表示されます。 ただし、次の場合を考えてみましょう。
var script = document.createElement('script');
script.innerHTML = 'eval("alert(1);")';
=document.getElementById('body').appendChild(script);
初期スクリプトの実行中は、 の eval
呼び出しがブロックされます。 つまり、初期スクリプト ランタイムは許可されますが、スクリプト内の動作はページの CSP によって規制されます。 したがって、拡張機能で DOM 挿入スクリプトを記述する方法によっては、ページの CSP に対する変更が拡張機能の動作に影響する可能性があります。
コンテンツ スクリプトはページの CSP の影響を受けないため、DOM によって挿入されたスクリプトではなく、拡張機能の動作をコンテンツ スクリプトにできるだけ多く配置する大きな理由です。
この作品は 、クリエイティブ・コモンズ属性4.0国際ライセンスに基づきライセンスされています。