“Content-Security-Policy: upgrade-insecure-requests”でHTTPSページの混在コンテンツを解消する方法

[レベル: 上級]

安全なHTTPSで通信するページで、安全ではないHTTPで読み込ませるリソースが存在すると、「混在するコンテンツ」 のエラーが発生します。
Content-Security-Policy: upgrade-insecure-requests という仕組みを使うと、混在するコンテンツが存在している場合でもHTTPSで強制的に読み込ませることが可能です。
つまり、混在するコンテンツエラーを回避することができます。

HTTPSページでHTTP読み込みさせると「混在するコンテンツ」が発生

たとえば、HTTPSのページに次のような画像のタグが書かれていたとします。

<img src="http://example.com/image.jpg">

src属性が、https ではなく http になっています。

この状態だとブラウザでは混在コンテンツ (Mixed content) が検出されます。

Mixed content reported on Security Panel

完全には安全ではないためアドレス欄には鍵マークは付きません。

ブラウザ(とその設定)によっては、HTTPコンテンツはブロックされ読み込まれないこともあるでしょう。

Content-Security-PolicyでHTTPS読み込みを強制

ここで役に立つのが、Content-Security-Policyupgrading insecure request です。
Content-Security-Policy に新たに追加された仕様です。

Upgrading insecure request を設定すると、HTTPSページでHTTP読み込みが発生している場合、ブラウザはそのコンテンツをHTTPではなくHTTPSで読み込みます。
したがって混在するコンテンツエラーを回避できるのです。

Upgrade-insecure-requests の設定方法

Content-Security-Policy の upgrade-insecure-requests は、HTTPヘッダーかあるいはmetaタグで設定できます。

HTTP ヘッダー

HTTPヘッダーで設定する場合は、.htaccess(または、httpd.conf)に次の記述を追加します。

Header set Content-Security-Policy: upgrade-insecure-requests

meta タグ

meta タグで設定する場合は、次をHTMLのheadセクションに追加します。

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

HTTP ヘッダーまたは meta タグ のいずれかで upgrade-insecure-requests を設定すれば、HTTPSページでのHTTPコンテンツをブラウザはHTTPSで読み込もうとします。
そのコンテンツをもしHTTPで入手できない際は、通常どおりHTTPで読み込みます(もちろん結果として、混在するコンテンツエラーが出る)。

対応するブラウザ

upgrade-insecure-requests は新しい仕様です。
対応するブラウザを調べたのですが、調べきれていません。
少なくとも、最新のChromeとFirefoxはサポートしているはずです。

Content Security Policy には、CSP1.0 と CSP Level 2 の2つがあり、Safari と Internet Explorer は CSP Level 2 を最新バージョンでもサポートしていないようです。
upgrade-insecure-requests が CSP Level 2 に含まれるなら Safari と IE は対応していないということになりそうです(どなたかに、upgrade-insecure-requestsのブラウザサポート状況を調べていただけると嬉しいです)。

混在するコンテンツはコードレベルで解消することが最も適切な対応です。
しかし、大規模なサイトになると完璧な対応が難しいこともあるでしょう。
HTTPS移行時に発生する、混在するコンテンツの”応急的”な処置として upgrade-insecure-requests は役立ちそうです。

Content-Security-Policy には、ほかにも混在するコンテンツを発見してログに出力だけしたり、混在するコンテンツを完全にブロックするなどのオプションがあります。
くわしくは、GoogleのデベロッパーサイトのMixed Content解説ページを参照してください。

[h/t Thomas Steiner]