アクセス解析は同意後だけ使います。詳細

安全と会社での利用

セキュリティヘッダーとは⁠|HSTS・CSPなど6つの意味と、壊さない設定の順番

要点この記事の答え
  1. 6つは、HSTS、CSP、nosniff、埋め込み、参照元、機能の制限です。
  2. 壊れにくい順に、1つずつ入れて確かめます。
  3. HSTSは短い期間から、CSPは報告だけから始めます。
セキュリティヘッダーは、HSTS、CSP、nosniff、枠への埋め込み、Referrer-Policy、Permissions-Policyの6つで、壊れにくい順に1つずつ入れ、HSTSは短い期間から、CSPは報告だけのモードから始める。

セキュリティヘッダーは、Webサイトが返す応答に付ける、ブラウザへの指示です。 HSTSは「次からはhttpsだけで来て」、CSPは「読み込んでよいものの出どころはここだけ」、というように、ブラウザの動きを絞ります。ここでは、当サイトの無料ツールが確かめる6つ(Strict-Transport-Security、Content-Security-Policy、X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy)を扱います。

設定を間違えると、サイトが開けなくなったり、スクリプトが動かなくなったりします。特に、HSTSのpreloadと、CSPには注意が必要です。この記事では、6つの意味、安全に始められる値、間違えたときに起きること、入れていく順番、Apache、nginx、Cloudflareでの設定の仕方を、公式の資料にもとづいて整理します。

内容は、2026年10月23日に、MDN Web DocsのStrict-Transport-Security、Content Security Policy、X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy、HSTS preloadの公式サイト、Apacheのmod_headers、nginxのngx_http_headers_module、CloudflareのResponse Header Transform Rules、Managed Transforms、HSTSの説明と照らし合わせました。

自分のサイトにどのヘッダーがあるかは、サイトのPHPとヘッダーを確かめる無料ツールで、通常のGETを1回送るだけで見られます。

6つのヘッダーの一覧

ヘッダー何をするか始めやすい値間違えると
ヘッダーStrict-Transport-Security(HSTS)何をするか次からはhttpsだけでアクセスさせる始めやすい値短い期間から始める間違えるとhttpsが使えなくなると、サイトが開けなくなる
ヘッダーContent-Security-Policy(CSP)何をするか読み込んでよい出どころを絞る始めやすい値まず報告だけのモードで試す間違えるとスクリプトや画像が読み込まれなくなる
ヘッダーX-Content-Type-Options何をするかファイルの種類の推測を止める始めやすい値nosniff間違えると種類を間違えて返しているスクリプトが動かなくなる
ヘッダーX-⁠Frame-⁠Options(またはframe-⁠ancestors)何をするかほかのサイトの枠への埋め込みを防ぐ始めやすい値DENY、または埋め込みが要るならSAMEORIGIN間違えると自社の別ページや提携先への埋め込みができなくなる
ヘッダーReferrer-⁠Policy何をするかリンク先へ送る元ページの情報を絞る始めやすい値strict-origin-when-cross-origin間違えると提携先が、元のページのURLを使っている場合に困る
ヘッダーPermissions-Policy何をするかカメラや位置情報などを使えるページを絞る始めやすい値使わない機能を空にする間違えると自社のページが機能を使っていると、使えなくなる

「始めやすい値」は、MDNの例と説明にもとづく、当サイトの提案です。サイトによって、適した値は変わります。

01 HSTS(Strict-⁠Transport-⁠Security)

MDNによると、max-ageは、ブラウザが「このサイトはhttpsだけで開く」と覚えておく秒数です。includeSubDomainsを付けると、サブドメインにも適用されます。MDNの例は、次の2つです。

設定
Strict-Transport-Security: max-age=31536000; includeSubDomains
設定
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

MDNは、始めの値を勧めてはいません。1年(31536000秒)は、preloadに必要な最小の値としています。

壊れるとき

  • httpsが使えなくなると、サイトが開けなくなります。 Cloudflareの説明では、httpsをやめると、max-ageの間、または再びhttpsを有効にするまで、訪問者はサイトを開けなくなります
  • サブドメインも対象です。 includeSubDomainsを付けると、httpsに対応していないサブドメインは開けなくなります
  • preloadは、簡単には戻せません。 hstspreload.orgは、一覧への登録は簡単には取り消せず、Chromeの更新で変更が利用者に届くまでに数か月かかるとしています。サイト全体とすべてのサブドメインを、長期にわたってhttpsで出せると確信できるときだけ申し込むよう書かれています。また、preloadを既定で付けないよう求めています
  • httpでは効きません。 MDNによると、HSTSをやめる場合はmax-age=0にしますが、これは、ブラウザがhttpsで接続して、応答を受け取ったときにだけ効きます

当サイトの勧め方

短い期間から始めて、問題がなければ延ばします(当サイトの提案で、MDNの推奨ではありません)。たとえば、数分、1週間、1か月、1年の順です。includeSubDomainsは、すべてのサブドメインがhttpsで動くことを確かめてから付けます。preloadは、最後に、必要なときだけです。

02 CSP(Content-⁠Security-⁠Policy)

CSPは、読み込んでよいスクリプト、画像、スタイルの出どころを、ブラウザに伝える設定です。MDNの例は、次のとおりです。

設定
Content-Security-Policy: default-src 'self'; img-src 'self' example.com

default-src 'self'は、同じ出どころからだけ読み込む、という意味です。img-srcで、画像にだけ別の出どころを足しています。

壊れるとき

MDNによると、CSPにdefault-srcかscript-srcがあると、そのままではインラインのJavaScriptは動きません。<script>の中のコード、onclickのような属性、javascript:のURLが対象です。eval()なども止まります。Googleアナリティクスのタグや、チャットのウィジェットなど、外から読み込むものや、ページに直接書いたスクリプトを使っているサイトは、設定を間違えると、動かなくなります。

'unsafe-inline'で止まらないようにできますが、MDNは、CSPの目的の多くを失うので避けるよう書いています。同じ指定にnonceかハッシュがあると、'unsafe-inline'はブラウザに無視されます。代わりに、ランダムな値(nonce)か、ハッシュを使う方法があります。nonceは、応答ごとに変わる値が必要なので、静的なHTMLでは使えません。

まず、報告だけのモードから

MDNは、CSPを報告だけのモードで出せると説明しています。このモードでは、ポリシーは強制されず、違反だけが報告先に送られます。

設定
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"

MDNに、段階ごとの手順は書かれていません。MDNの説明から導ける進め方は、次のとおりです(当サイトの整理です)。

  1. 報告だけのモードで出す
  2. 報告された違反を見て、正当なものは許可し、インラインのスクリプトはnonceかハッシュに変える
  3. 違反が出なくなったら、強制するヘッダーに切り替える

報告だけのモードは、<meta>では使えません。また、報告を受ける場所は、自分で用意する必要があります。

03 X-⁠Content-⁠Type-⁠Options

値はnosniffだけです。MDNによると、スクリプトやスタイルの要求では、返された種類(MIME type)が、JavaScriptやtext/cssでなければ、ブラウザはその応答を止めます。それ以外では、ブラウザは中身から種類を推測せず、示された種類をそのまま使います。

壊れるのは、スクリプトやスタイルを、正しくない種類で返しているサイトです。入れる前に、スクリプトとスタイルが正しい種類で返っているかを確かめます。

04 X-⁠Frame-⁠Options と frame-⁠ancestors

MDNの説明では、DENYは、どこの枠にも埋め込めません。SAMEORIGINは、同じ出どころのページからだけ埋め込めます。ALLOW-FROMは廃止されていて、モダンなブラウザは無視します。

より細かく決めたいときは、CSPのframe-ancestorsを使います。MDNは、埋め込まれる必要がなければ、frame-ancestors 'none'にするよう書いています。

設定
Content-Security-Policy: frame-ancestors 'none'

当サイトのツールは、X-Frame-Optionsという名前のヘッダーがあるかを見ます。frame-ancestorsだけを設定しているサイトでは、X-Frame-Optionsが「要確認」と出ることがあります。その場合は、CSPの中身を自分で確かめてください。

05 Referrer-⁠Policy

リンクを開いたときに、元のページのURLのどこまでを、リンク先に伝えるかを決めます。MDNによると、何も設定しないか、値が正しくない場合、最近のブラウザはstrict-origin-when-cross-originを使います。つまり、設定がなくても、何も送られないわけではありません。

strict-origin-when-cross-originでは、同じサイトの中では完全なURLが、ほかのサイトにはサイト名だけ(https同士の場合)が送られ、httpsからhttpへは何も送られません。MDNは、unsafe-urlは、非公開の情報を含むURLを漏らすおそれがあるとして、注意を求めています。

設定
Referrer-Policy: strict-origin-when-cross-origin

06 Permissions-⁠Policy

カメラ、マイク、位置情報などの機能を、どのページで使えるようにするかを決めます。MDNの例は、次のとおりです。()は、その機能をすべて使えなくする、という意味です。

設定
Permissions-Policy: camera=(), microphone=(), geolocation=()

MDNは、このヘッダーを実験的で、一部のブラウザでは使えないと説明しています。本番で頼る前に、対応状況を確かめてください。また、<iframe>で外のサービス(地図や動画など)を埋め込んでいるサイトは、その機能まで止めないよう注意します。

入れていく順番

6つを一度に入れると、どれが原因で壊れたのか分からなくなります。壊れにくい順に、1つずつ入れます。この順番は、MDNなどの説明から整理した、当サイトの提案です。

順ヘッダー理由
順1ヘッダーReferrer-⁠Policy理由ブラウザの既定と近く、影響が小さい
順2ヘッダーX-Content-Type-Options理由種類を正しく返していれば、影響が小さい
順3ヘッダーX-⁠Frame-⁠Options、またはframe-⁠ancestors理由埋め込みを使っていないかを先に調べる
順4ヘッダーPermissions-Policy理由使っていない機能を止める
順5ヘッダーHSTS理由短い期間から始めて、延ばす
順6ヘッダーCSP理由最も壊れやすい。報告だけのモードから始める

1つ入れるたびに、トップページ、ログイン、問い合わせフォーム、決済など、大事なページを、ブラウザで開いて確かめます。

主なホスティングでの設定

Apache(.htaccess を含む)

mod_headersのHeaderディレクティブを使います。mod_headersの説明では、このディレクティブは.htaccessでも使え、上書きの種類はFileInfoとされています。つまり、サーバーの設定でAllowOverrideがそれを許していないと、.htaccessでは効きません。alwaysを付けると、エラーの応答にも付きます。

設定
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

mod_headersが有効でないと動きません。レンタルサーバーでは、.htaccessの書き方の制限がある場合があります。サーバー会社の説明を見てください。

nginx

ngx_http_headers_moduleのadd_headerを使います。注意点が2つあります。

  • 既定では、add_headerは、応答のコードが200、201、204、206、301、302、303、304、307、308のときだけ付きます。エラーの応答にも付けたいときは、alwaysを付けます
  • 上の階層(httpやserver)のadd_headerは、今の階層にadd_headerが1つもないときだけ引き継がれます。locationの中にadd_headerを1つ書くと、上の階層のものが消えます
設定
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Cloudflare

3つの方法があります。

  • Response Header Transform Rule ダッシュボードのRulesから「Create rule」、「Response Header Transform Rule」を選び、「Modify response header」で「Set static」にして、ヘッダーの名前と値を入れます。Cloudflareの説明では、同じ名前のヘッダーがあれば上書きされます。ダッシュボードの手順によると、1つのルールで30個まで設定できます
  • HSTS 「Edge Certificates」のページに、HSTSの設定があります。期間は1か月から12か月で選びます。httpsに対応してから有効にするよう、Cloudflareは警告しています
  • Managed Transforms の「Add security headers」 Cloudflareの説明では、X-Content-Type-Options(nosniff)、X-XSS-Protection、X-Frame-Options(SAMEORIGIN)、Referrer-Policy(same-origin)、Expect-CTを付けます。上の「始めやすい値」と違う値があり、Cloudflareも、サイトに影響する可能性があると書いています。使うなら、値を確かめてからにします

設定したあとに確かめる

  1. ブラウザの開発者ツールのネットワークの画面で、応答のヘッダーを見ます
  2. 無料ツールで、6つのヘッダーが「設定あり」になったかを見ます。このツールは、ヘッダーがあるかどうかを見るもので、値が適切かまでは判断しません。CSPの中身が強いか弱いか、HSTSの期間が十分かは、自分で確かめてください
  3. 大事なページを、実際に開いて、動くことを確かめます

よくある質問

HSTSとは何ですか?

次からはhttpsだけでアクセスするよう、ブラウザに覚えさせる設定です。httpsが使えなくなると、期間の間、サイトが開けなくなります。短い期間から始めて、延ばします。

HSTSのpreloadは付けたほうがよいですか?

必要なときだけです。hstspreload.orgは、一覧への登録は簡単には取り消せず、Chromeでは変更が届くまで数か月かかるとしています。サイト全体とすべてのサブドメインを長期にわたってhttpsで出せると確信できるときだけ申し込みます。

CSPを入れたらサイトが動かなくなりました。どうすればよいですか?

まず、強制するヘッダーを外します。そのうえで、報告だけのモード(Content-Security-Policy-Report-Only)で出して、報告された違反を見ながら、許可する出どころを足します。インラインのスクリプトは、nonceかハッシュに変えます。

セキュリティヘッダーは、全部入れないといけませんか?

必ずではありません。影響の小さいものから、1つずつ入れます。使っていない機能を止めるPermissions-Policyや、nosniffは、比較的入れやすいものです。CSPは、最後に報告だけのモードから始めます。

レンタルサーバーでも設定できますか?

Apacheなら、.htaccessで設定できる場合があります。ただし、サーバー会社によって、書き方の制限があります。サーバー会社の説明を見てください。Cloudflareを使っているなら、ダッシュボードから設定できます。