WordPressで例えるHTTPセキュリティヘッダーまとめ

2013年頃にはContent-Security-Policy(CSP)が使えるようになり、2019年頃までにはCOEP, COOP, CORP, CORSが使えるようになりました。

これらのヘッダーは度々アップデートされており、新しい値が設定できるようになっています。
Expect-CTのように不要になったヘッダーもあります。

セキュリティヘッダーについて調べると古い情報が出てきてしまいます。
しかも年々複雑化していて、今となっては何を設定すれば分からないという事態に陥りがちです。

それらを自分なりに整理してみました。

目次

HTTPセキュリティヘッダーとは

Webサーバーは、接続してきたユーザーに対してページを返却します。
このページを正しく制御するために付与するのがHTTPヘッダーです。

レスポンスヘッダーの例
レスポンスヘッダー内の文字列がHTTPヘッダー

HTTPヘッダーは自由に追加することができ、中にはセキュリティを強化するものもあります。
これがセキュリティヘッダーと言われています。

HTTPヘッダーの恩恵を受けられるのはサーバー側ではなくクライアント側です。
つまりここでのセキュリティ強化とは、接続してきたユーザーが安全にサイトを閲覧できるように保護することです。

セキュリティヘッダーの概要

このサイト(WordPress)に設定しているセキュリティヘッダーです。
手っ取り早く正解を知りたい方向けです。

Apache

Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set Permissions-Policy "geolocation=(),microphone=(),camera=()"
Header always set Cross-Origin-Resource-Policy "same-origin"
Header always set Cross-Origin-Embedder-Policy "unsafe-none"
Header always set Cross-Origin-Opener-Policy "same-origin-allow-popups"

Nginx

add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header Permissions-Policy "geolocation=(),microphone=(),camera=()" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "unsafe-none" always;
add_header Cross-Origin-Opener-Policy "same-origin-allow-popups" always;

上記ApacheとNginxの設定値の要約

ヘッダー名上記の設定の意味(要約)対策対象の攻撃
X-Content-Type-OptionsMIMEスニッフィングを無効化し、ファイル形式はContent-Typeで判定させるXSS
Content-Security-Policy通称CSP。別オリジンからの埋め込みコンテンツでの閲覧を禁止させるクリックジャッキング
Permissions-PolicyGPS、マイク、カメラの使用を禁止するプライバシーの侵害
Cross-Origin Resource-Policy通称CORP。別オリジンから直接リソースを参照する場合、レスポンスを空にさせるサイドチャネル攻撃、XS-Leaks
Cross-Origin-Embedder-Policy通称COEP。unsafe-noneは規定値なので設定しなくともよい※規定値なのでなし
Cross-Origin-Opener-Policy通称COOP。別オリジンからwindow.openerやpostMessageを利用できないようにさせるサイドチャネル攻撃、XS-Leaks

付与すべきヘッダー

X-Content-Type-Options

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

付与すべき理由:ブラウザにファイル形式を誤認させないため

ブラウザは、ファイルの中身を見てファイル形式を判別することがあります。
言い換えればファイル名がimage.pngでも、中身がJavaScriptっぽければJavaScriptとして解釈することがあります。

この仕様が脆弱性の原因になってしまいました。(特に昔のIEが悪名高かった)
ファイル形式がセットされているContent-Typeヘッダーを無視して勝手に判別することが問題だったので、Content-Typeヘッダーに強制的に従わせるようにするのが、このX-Content-Type-Optionsヘッダーです。

設定値

設定値は「nosniff」だけです。
WordPressに限らず、特に理由がなければ「X-Content-Type-Options "nosniff"」を設定していいでしょう。

Permissions-Policy

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

付与すべき理由:プライバシーの侵害を防ぐため

Permission-Policyは2017年頃から登場したヘッダーです。聞いたことがない方も多いと思います。
JavaScriptから位置情報などを取得できますが、それらを機能単位で禁止することができます。

位置情報とマイクとカメラの場合、もしこのヘッダーを設定しなくても、JavaScriptからアクセスがあった場合はユーザーに許可を求めるダイアログが表示されます。
このヘッダーを使用するとそれすらも表示されなくなり、JavaScriptのコード上はエラーが発生するようになります。

WordPressでは?

このサイトでは「Permissions-Policy "geolocation=(),microphone=(),camera=()"」を設定しています。
左から順に、位置情報、マイク、カメラを使用禁止にしています。

通常、WordPressではこれらの機能を使うことはないでしょうから、無効にしてもよいでしょう。
もし使用するものがあれば、記述ごと削除してください。

ちなみにプライバシーの侵害を防ぐためにこのヘッダーを設定するとしましたが、本当は対象の機能がたくさんあります。詳しくは以下をどうぞ。(随時更新されるっぽいので見ておくといいかも)

上記のような情報を見ると、何を制限すべきか迷うかもしれません。
本当に重要な機能にアクセスする時はユーザー側に確認ダイアログが出ますから、必ずしも設定しなければならないものではない、ということを念頭に入れましょう。

Strict-Transport-Security (HSTS, STS)

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

付与すべき理由:HTTPS通信を強制させるため

1度でもHTTPSで通信したサイトなら、2回目以降もHTTPSを強制するヘッダーです。

なぜそうする必要があるかというと、一瞬でもHTTP通信をすると暗号化していないデータが漏えいする可能性があるからです。
最初から最後までHTTPS通信をさせることで、通信中の暗号化していないデータを減らします。

※Google Chrome 90からHTTPSを優先する仕様に変更されたので、このヘッダーもそのうち必要なくなるかもしれません。

窓の杜
「Google Chrome 90」から実施 ~アドレスバーに入力したURLはデフォルトでHTTPS接続扱いに/まずデスクト...  米Googleは3月23日(現地時間)、「Google Chrome」のアドレスバーに入力したURLの扱いを変更し、デフォルトでHTTPS接続と扱う計画を明らかにした。「Chrome 90」より実...

設定値

このサイトでは「Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"」を設定しています。

max-ageにはHTTPSで強制的に接続する期間を設定します。63072000秒=2年間です。

includeSubDomainsはサブドメインにもHSTSを強制します。
1点だけ注意事項があって、example.comがHTTPSだけどsub.example.comはHTTP、という環境だとsub.example.comに接続できなくなるので注意が必要です。

3つ目のpreloadは、GoogleのHSTS Preloadサービスのための設定です。

あわせて読みたい

これに登録しておくと、Chrome/Edge/Firefox/Safariなどの主要ブラウザで、2回目だけでなく初回アクセス時にもHTTPSで接続するようになります。
ただし、申請には以下の条件が必要です。

  • max-ageは31536000以上であること (1年間。推奨は2年間の63072000)
  • includeSubDomainsがあること
  • preloadがあること

つまり「Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"」にして、HSTS Preloadに申請しておくと完璧です。
WordPressに限らず、これを設定していいでしょう。

Content-Security-Policy (CSP)

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

付与すべき理由:クリックジャッキングを防ぐため

iframeなどのページ内埋め込み機能を制限することで、クリックジャッキングを防ぐことができます。
クリックジャッキングというのは、埋め込み機能を悪用して見た目とは異なる場所をクリックしたことにしてしまう手法のことです。

設定値

  • frame-ancestors 'self'
    iframeなどの読み込み条件を同じドメイン(サブドメインを除く)に限定します。
    異なるドメインを許可したい場合は、「frame-ancestors 'self' domain1.com domain2.com」のようにしてください。

後述しますが、CSPのframe-ancestorsはX-Frame-Optionsと同じものです。
より推奨されているCSPを紹介しました。
WordPressであってもなくても「frame-ancestors 'self'」は設定してよいでしょう。

ちなみにCSPにはupgrade-insecure-requestsという値もありますが、こちらはHSTSを設定している場合は不要です。

実は初心者お断りのヘッダー「CSP」

詳しい方はこの説明を見て「あれ?」と思ったかもしれません。
CSPにはframe-ancestorsやupgrade-insecure-requests以外にもたくさんの値があり、非常に複雑で奥が深いヘッダーです。

本当のCSPはスクリプトやリソースの読み込みと実行に制約をかけることでセキュリティを強化する仕組みで、evalなどの危険を伴うスクリプトも制限できます。しかしホワイトリスト方式で許可していく感じなので、いきなり設定すると画像が表示されなかったりページが動作しなくなったりします。

connect-src pagead2.googlesyndication.com;
img-src pagead2.googlesyndication.com;
frame-src googleads.g.doubleclick.net tpc.googlesyndication.com;
script-src pagead2.googlesyndication.com partner.googleadservices.com tpc.googlesyndication.com www.googletagservices.com adservice.google.com adservice.google.ad adservice.google.ae adservice.google.com.af adservice.google.com.ag adservice.google.com.ai adservice.google.al adservice.google.am adservice.google.co.ao adservice.google.com.ar adservice.google.as adservice.google.at adservice.google.com.au adservice.google.az adservice.google.ba adservice.google.com.bd adservice.google.be adservice.google.bf adservice.google.bg adservice.google.com.bh adservice.google.bi adservice.google.bj adservice.google.com.bn adservice.google.com.bo adservice.google.com.br adservice.google.bs adservice.google.bt adservice.google.co.bw adservice.google.by adservice.google.com.bz adservice.google.ca adservice.google.cd adservice.google.cf adservice.google.cg adservice.google.ch adservice.google.ci adservice.google.co.ck adservice.google.cl adservice.google.cm adservice.google.cn adservice.google.com.co adservice.google.co.cr adservice.google.com.cu adservice.google.cv adservice.google.com.cy adservice.google.cz adservice.google.de adservice.google.dj adservice.google.dk adservice.google.dm adservice.google.com.do adservice.google.dz adservice.google.com.ec adservice.google.ee adservice.google.com.eg adservice.google.es adservice.google.com.et adservice.google.fi adservice.google.com.fj adservice.google.fm adservice.google.fr adservice.google.ga adservice.google.ge adservice.google.gg adservice.google.com.gh adservice.google.com.gi adservice.google.gl adservice.google.gm adservice.google.gr adservice.google.com.gt adservice.google.gy adservice.google.com.hk adservice.google.hn adservice.google.hr adservice.google.ht adservice.google.hu adservice.google.co.id adservice.google.ie adservice.google.co.il adservice.google.im adservice.google.co.in adservice.google.iq adservice.google.is adservice.google.it adservice.google.je adservice.google.com.jm adservice.google.jo adservice.google.co.jp adservice.google.co.ke adservice.google.com.kh adservice.google.ki adservice.google.kg adservice.google.co.kr adservice.google.com.kw adservice.google.kz adservice.google.la adservice.google.com.lb adservice.google.li adservice.google.lk adservice.google.co.ls adservice.google.lt adservice.google.lu adservice.google.lv adservice.google.com.ly adservice.google.co.ma adservice.google.md adservice.google.me adservice.google.mg adservice.google.mk adservice.google.ml adservice.google.com.mm adservice.google.mn adservice.google.ms adservice.google.com.mt adservice.google.mu adservice.google.mv adservice.google.mw adservice.google.com.mx adservice.google.com.my adservice.google.co.mz adservice.google.com.na adservice.google.com.ng adservice.google.com.ni adservice.google.ne adservice.google.nl adservice.google.no adservice.google.com.np adservice.google.nr adservice.google.nu adservice.google.co.nz adservice.google.com.om adservice.google.com.pa adservice.google.com.pe adservice.google.com.pg adservice.google.com.ph adservice.google.com.pk adservice.google.pl adservice.google.pn adservice.google.com.pr adservice.google.ps adservice.google.pt adservice.google.com.py adservice.google.com.qa adservice.google.ro adservice.google.ru adservice.google.rw adservice.google.com.sa adservice.google.com.sb adservice.google.sc adservice.google.se adservice.google.com.sg adservice.google.sh adservice.google.si adservice.google.sk adservice.google.com.sl adservice.google.sn adservice.google.so adservice.google.sm adservice.google.sr adservice.google.st adservice.google.com.sv adservice.google.td adservice.google.tg adservice.google.co.th adservice.google.com.tj adservice.google.tl adservice.google.tm adservice.google.tn adservice.google.to adservice.google.com.tr adservice.google.tt adservice.google.com.tw adservice.google.co.tz adservice.google.com.ua adservice.google.co.ug adservice.google.co.uk adservice.google.com.uy adservice.google.co.uz adservice.google.com.vc adservice.google.co.ve adservice.google.vg adservice.google.co.vi adservice.google.com.vn adservice.google.vu adservice.google.ws adservice.google.rs adservice.google.co.za adservice.google.co.zm adservice.google.co.zw adservice.google.cat

※参考サイト - Content-Security-Policy (CSP) for Google AdSense

上記はGoogle Adsenseを許可する設定です。CSPに厳しいポリシーを適用させつつサイト内にAdsense広告を掲載する際には、上記の設定をしなければなりません。

サイトによっては、他にもAnalyticsやCDN系やYoutubeやTwitterなどリストアップしなければいけないものがたくさんあります。
各種アップデートやサービスの仕様変更があった場合も対応が必要になります。
(CSP自身も割と頻繁に更新されています)

またWordPressの場合、厳しめのポリシーを設定すると管理画面が動かなくなるため、更なる対処が求められます。

本来のCSPの目的は、アプリケーションの設計者がセキュリティ設計をした上でXSSなどのセキュリティ的に問題がある実装をエンジニアが意図せず行っても問題ないようにする機能です。
アプリケーションの内部事情に詳しい設計者と実装者でなければ有効活用が難しいわけです。

本記事の内容以上の設定を運用する場合は分析必至なので、頭を悩ませることになるでしょう。

WordPressの場合、ユーザーはWordPressのテーマやプラグイン側の仕様に従わざるを得ないので、「frame-ancestors 'self'」以外の付与は現実的ではありません。

付与しなくていいヘッダー

X-XSS-Protection

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-XSS-Protection

付与しない理由:主要なブラウザがもう対応していないため

過去にはFirefox以外の全てのブラウザが対応していましたが、現在はどのブラウザも対応していません。
Safariは長い間対応していましたが、2022年3月にリリースされたSafari 15.4で対応を打ち切っています。

Removed the XSS Auditor.

Safari 15.4 Release Notes | Apple Developer Documentation

対応していた頃には、設定するとXSS攻撃を防ぐためのフィルタが有効になりました。
しかし、XSSフィルタでも防げない攻撃があることから廃止されました。

あわせて読みたい

メンテナンス上の問題も抱えていたようです。
詳しい事情は、当時X-XSS-Protectionに対応しなかったFirefoxの開発者によるやり取りが参考になります。
※英語

あわせて読みたい
528661 - (xssfilter) Heuristics to block reflected XSS via X-XSS-Protection HTTP header RESOLVED (nobody) in Core - Security. Last updated 2019-08-22.

X-Frame-Options

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Frame-Options

付与しない理由:CSPのframe-ancestorsで代用できるため

「Content-Security-Policy: frame-ancestors 'self';」を指定することで「X-Frame-Options SAMEORIGIN;」と同等になります。そのため、W3CによってX-Frame-Optionsからframe-ancestorsに置き換えることが推奨されています。

frame-ancestors controls the protected resource’s ability be embedded in other documents. It is meant to supplant the X-Frame-Options HTTP request header.

1.1. Changes from Level 1

Referrer-Policy

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

付与しない理由:規定値が「strict-origin-when-cross-origin」になったため

リファラとは参照元のことです。
リンクをクリックしたときに、どのページから遷移したかの情報も送られます。

リファラには参照元のURLが含まれているので、URLにIDやメールアドレスなどの情報が入っていると、その情報まで送られてしまいます。
この情報を制御できるのがReferrer-Policyヘッダーです。

以前は「Referrer-Policy "strict-origin-when-cross-origin"」の設定が推奨されていました。この設定値は同じサイト内、かつ、HTTPSからHTTPS(もしくはHTTPからHTTP)に遷移する場合のみリファラを送信するものです。

2021年4月以降は主要な全てのブラウザの規定値が「strict-origin-when-cross-origin」に変更されました。

そのため、特に設定せずともセキュアな状態を保てます。

必要がなくなったヘッダーではなく、他の設定値も設定可能ですし、2021年4月より前のブラウザに対応する場合は設定が必要です。
ケースバイケースで使うかどうかを決めましょう。

Expect-CT

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Expect-CT

付与しない理由:2021年6月以降、Expect-CTが必要なくなったため

2015年以降、Certificate Transparencyという不正な証明書を検知する仕組みが有効になりました。
この仕組みの実現には、証明書にSCTと言われる情報の埋め込みが必要です。
SCTに対応した証明書が普及するまでに時間がかかるので、移行期間中はSCTに対応した証明書と対応していない証明書が入り乱れていました。

そこで、SCTに対応した証明書であることをExpect-CTを付けて伝えていた時期があります。
2021年6月でSCTに対応していない証明書が全て失効したため、現在はExpect-CTを付けなくても対応しているものとして認識するようになりました。

限られた状況で付与すべきヘッダー

ここで紹介するHTTPヘッダーは、主にJavaScriptで使える一部機能のために存在しています。

はじめに

「同一オリジン」という言葉の意味を理解しないと、この項のHTTPヘッダーは理解できないと思います。
以下が分かりやすいのでどうぞ。

https://www.tohoho-web.com/ex/same-origin-policy.html

CORSについて

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

JavaScriptの機能には、リアルタイムにサーバーと通信するためのXMLHttpRequestなどの機能があります。
同じサイト内の通信であればほぼ自由に通信できますが、そうでなければ決められた制約の中で通信をしなければなりません。

そこで生まれたのがCORS (Cross-Origin Resource Sharing)という考えです。
予め指定したオリジン間であれば制約を取り払った上で通信を行うことができます。

Access-Control-Allow-Origin

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

CORSに基づいて許可を行うヘッダーがAccess-Control-Allow-Originヘッダーです。

JavaScriptを使って、サイトA(https://example-a.com) からサイトB(https://example-a.com) のリソースにアクセスするとき、異なるサイトなので、サイトBはアクセスを拒否することがあります。
この場合、サイトBはAccess-Control-Allow-Originヘッダーを設定していないものとします。

そこで、サイトBは以下のヘッダーを返すようにします。

Access-Control-Allow-Origin: https://example-a.com

上記は「サイトBはサイトAを許可する」という意味になります。
これでサイトA以外からのアクセスを拒否しつつ、サイトAだけを許可する設定が可能です。

WordPressでは?

基本的にCORSは設定しなくていいです。
というのも、通常、WordPress内のリソースのアクセスは同サイトの中だけで完結するからです。

CORSはシステムの管理者、開発者が真価を発揮できるヘッダーです。
ユーザー向けではありません。

CORP/COEP/COOPについて

CORSとは別に、JavaScriptに存在する機能のうち、2018年に突如発見されたSpectreという脆弱性の影響を受ける機能が使用できなくなる or 制限を受ける事件がありました。

それでは今まで動作したシステムが動作しなくなってしまいます。
そこで「特定の条件下ならば制限なく使ってもいい」という発想のもと策定されたのが以下です。

  • CORP (Cross-Origin-Resource-Policy)
  • COEP (Cross-Origin-Embedder-Policy)
  • COOP (Cross-Origin-Opener-Policy)

この3つに関しては、以下の方(Chromeの開発者の1人)の記事が詳しいので、興味があればご覧ください。

Tender Surrender
SharedArrayBuffer と過渡期な cross-origin isolation の話 Spectre 前提のウェブで、標準技術を使って `SharedArrayBuffer` や高精細タイマーをブラウザで有効にする cross-origin isolation と、その課題および現時点での対応策に...

Spectreって何? という方はこちらをご覧ください。

MDN Web Docs
SharedArrayBuffer - JavaScript | MDN SharedArrayBuffer オブジェクトは、一般的な、生のバイナリーデータバッファーを表すために使用されます。ArrayBuffer オブジェクトと似ていますが、こちらは共有メモリー...

つまりCORP/COEP/COOPを使用しなければ「JavaScriptにおいてSpectreの影響を受ける機能」は使用できないということです。

しかしはっきり言ってしまうと、それらの機能はほとんどのWebアプリケーションで使用しません。
特殊なテーマやプラグインでも入れない限り、WordPressでも使用しないでしょう。
※もちろん、あなたが作っているWebシステムでSharedArrayBufferなどを使用する場合は別です

WordPressではCORP/COEP/COOPも設定しなくていいです。

あえてWordPressにCORP/COEP/COOPを設定してみる

外部サイトからWordPress内のリソースにアクセスする場合は、CORSで外部サイトを許可しなければいけないかもしれません。
そのような状況はWordPressにおいては通常ないので、このサイトでは設定していません。

しかし、CORP/COEP/COOPに関しては、設定する意味がないというわけではありません。

「JavaScriptにおいてSpectreの影響を受ける機能」を使っていないのならば設定する意味が全くないかと言われるとそうでもなく、これらのヘッダーはWebページ内のデータの取り扱いに厳しいルールを設けられるので、設定すればワンランク上のセキュリティを確保できます。

私のWordPressは、あえてCORP/COEP/COOPを設定して運用しています。
個人的な興味のためです。

しかし、得られるメリットに対してデメリットが大きいです。
これらのヘッダーは理解も運用も難しく、不具合を引き起こすことがあります。

CORP/COEP/COOPはその新しさと難解さゆえに資料がとても少ないです。
試しに設定してみたいと思っている方やWebアプリケーションを作っている方の参考資料になればいいと思って文字を起こしましたので、よく分からない場合は設定しないでください。

Cross-Origin-Resource-Policy (CORP)

https://developer.mozilla.org/ja/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)

2019年頃から使えるようになったヘッダーです。以下のいずれかを設定できます。

  • cross-origin (デフォルト値)
    いかなるオリジンからのリクエストでもリソースを読み込めます。
  • same-site
    同じサイトからのリクエストのみリソースを読み込めます。
  • same-origin
    同じオリジンからのリクエストのみリソースを読み込めます。

cross-originが最も緩く、same-originが最も厳しいです。
cross-originでは別オリジンからもリソースを参照できますが、same-originにするとそういったリソースのアクセスを拒否できます。

自分のサイトの画像のURLを勝手に使われることを禁止したい場合にも使用できます。
ただ、別オリジンからimgタグなどで参照できなくなるだけで、画像のURLを直接叩いて閲覧することは可能です。

WordPressでは?

same-origin推奨です。
通常の用途であれば、リソースの参照はWordPressを設置しているオリジン内で完結するからです。

ただし、ラッコツールズのOGP画像確認ツールのような外部サービスは使えなくなります。
このサービスはサイトへの直リンクをページに埋め込んでいるためです。
外部サービス周りの連携が取れなくなる恐れはあるので、心配な方は素直に設定しないかcross-originにしてください。

なお、LINEやTwitterやFacebookなどSNSのOGP画像には影響を及ぼしません。
OGP画像が表示されなくなる心配は不要です。

なぜかというと、これらはOGP画像を各社のCDNに保存するプログラムがサービス側で動作しており、実際のユーザーのブラウザにはCDNを通して配信されるからです。
ユーザーがTwitterを開いてOGP画像にアクセスする時には、Twitterのサーバーに画像が保存されており、それを参照するので問題なく閲覧できるというからくりです。

ちなみにOGP画像というのは、LINEやTwitterにURLを張り付けた時に表示される画像のことです。
この画像はサイトの運営者側が用意しています。

Cross-Origin-Embedder-Policy (COEP)

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy

2020年から使えるようになったヘッダーです。
ページ内の埋め込みリソースに対して読み込み制限を付けられます。

以下のいずれかを設定できます。

  • unsafe-none (デフォルト値)
    CORSやCORPがなくても、異なるオリジンのリソースを取得することを許可します。
  • credentialless
    CORSやCORPがなかった場合、異なるオリジンのリソースを取得することを許可しますが、クレデンシャルを送信しません。CORSかCORPがあった場合はrequire-corpと同様です。
  • require-corp
    同一オリジンからのリソースか、異なるオリジンからロード可能であるとCORSかCORPで明示的に指定したリソースのみをロードすることができます。

unsafe-noneが最も緩く、require-corpが最も厳しいです。
require-corpの効力が何なのかというと、取得するリソースのHTTPヘッダーに対して以下を確認します。

  • CORPもしくはCORSが付いているか?
  • 付いていた場合、読み込みが許可されているか?

上記をどちらも満たした場合だけリソースが読み込まれます。満たさなければ読み込みが失敗します。

ちなみにcredentiallessのクレデンシャルとは、Cookie・クライアント証明書・Authorizationヘッダーによる認証情報のことです。
埋め込みリソースがそれらに依存しないことが分かっていればcredentiallessでいいでしょう。

WordPressでは?

unsafe-none推奨です。(つまり、WordPressでは付与すべきでないということです)
credentiallessやrequire-corpは大半の埋め込みコンテンツを表示できなくなるからです。

例えば、require-corpを指定するとTwitterとGoogle Mapが表示できなくなります。
credentiallessを指定するとTwitterは問題なく表示できますが、Google Mapは表示できません。
※2022年時点で確認。サービス側の対応が進めば改善されるかもしれません

また、Google Adsenseにも影響を及ぼす可能性もあります。
Adsense広告はCookieに依存しているため、Cookieを送信できなくなると不具合を起こすと思われます。
このような場合はunsafe-noneで運用しなければなりません。

Cross-Origin-Opener-Policy (COOP)

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy

COEPと同時期に使えるようになったヘッダーです。以下のいずれかを設定できます。

  • unsafe-none (デフォルト値)
    異なるオリジンからでも、window.openerを介して元のサイトにアクセスできます。
  • same-origin-allow-popups
    same-originと同様に同一オリジン内に限定されますが、ポップアップウィンドウの場合のみwindow.openerを介して元のサイトのデータにアクセスできます。
  • same-origin
    同一オリジンの場合のみ、window.openerを介して元のサイトにアクセスできます。

unsafe-noneが最も緩く、same-originが最も厳しいです。

same-origin-allow-popupsですが、世の中にはポップアップウィンドウに依存した既存の処理(OAuth、支払いなど)が多いため、緩和策としてこの値が用意された経緯があります。

WordPressでは?

same-origin-allow-popups推奨です。
ポップアップウィンドウに依存しているプラグインでも問題なく動作させるようにするためです。(Googleなどの外部アカウントでログインする機能や決済機能があるプラグインが該当するでしょう)

余談ですが、COOPを付けなかった場合でも、記事内のリンクに関しては対策済みです。

ブロックエディタで記事内のリンクを作り、新しいタブで開く設定にした場合、WordPressは自動的にnoopenerを付けるので、記事内のリンク先からリンク元を参照することができません。
WordPressでCOOPを使う意味があるとすれば、プラグインなどが生成したリンクやスクリプトからwindow.open()でタブ/ウィンドウを開いた場合のデータ漏えい防止ということになるでしょう。

  • URLをコピーしました!
目次