Webサイトのセキュリティ対策と聞くと、WAFの導入や脆弱性診断のような大がかりな取り組みを思い浮かべるかもしれません。しかし実際には、HTTPレスポンスにいくつかのヘッダーを追加するだけで、クリックジャッキング、クロスサイトスクリプティング(XSS)、MIME-Sniffing といった代表的な攻撃を未然に防げます。

問題は、こうしたセキュリティヘッダーの存在自体を知らないまま運用しているサイトが多い点です。SecurityHeaders.comで自社サイトのURLを入力すると、多くの中小企業サイトが「D」や「F」の評価を受けている現実に気づくはずです。OWASP Secure Headers Projectでも、これらのヘッダーはWebアプリケーションの基本防御策として体系的にまとめられており、OWASP HTTP Headers Cheat Sheetでは各ヘッダーの推奨値と非推奨値が一覧で確認できます。

この記事では、Webサイトに設定すべき7つのHTTPセキュリティヘッダーを1つずつ取り上げ、なぜ必要なのか、どう設定するのか、設定を誤るとどうなるのかを具体的に解説します。記事の後半では、京谷商会が自社サイトで実際にCloudflare Workersを使って7ヘッダーを一括設定した事例も紹介します。

HTTPセキュリティヘッダーが中小企業のWebサイトに欠かせない理由

HTTPセキュリティヘッダーとは、Webサーバーがブラウザに対して「このページをどう扱うべきか」を指示するレスポンスヘッダーの総称です。ブラウザはこの指示に従って、特定のスクリプトの実行を拒否したり、他のサイトへの埋め込みをブロックしたり、通信の暗号化を強制したりします。Googleのweb.devが公開するSecurity Headers Quick Referenceでも、各ヘッダーの役割と推奨設定がコンパクトにまとまっています。

セキュリティヘッダーの最大の利点は、アプリケーションのコードを一切変更せずにブラウザ側の防御機能を有効化できることです。サーバーの設定ファイルに数行追加するか、CDNの管理画面でオプションを有効にするだけで適用されます。

IPAが公開する「安全なウェブサイトの作り方 改訂第7版」でも、レスポンスヘッダーの適切な設定はWebアプリケーションのセキュリティ実装として明記されています。にもかかわらず、中小企業のサイトでは未設定のケースが目立ちます。理由はシンプルで、サイトの見た目や機能に影響しないため、設定しなくても「動いている」ように見えるからです。

しかし攻撃者は、こうした防御の欠落を確実に突いてきます。2025年末から2026年にかけて国内で相次いだWebサイト改ざんやフィッシング被害の中にも、適切なセキュリティヘッダーが設定されていれば被害を軽減できたケースが含まれています。JPCERT/CCの「インシデント報告対応レポート」を見ると、Webサイト経由の被害が依然として報告件数の上位を占めていることがわかります。セキュリティ対策の全体像については、当ポータルの「Webサイトのセキュリティ対策チェックリスト2026年版」も併せてご確認ください。

まず確認——自社サイトのセキュリティヘッダー診断

設定を始める前に、現状を把握することが先決です。以下の3つの方法で、自社サイトに設定されているセキュリティヘッダーを確認できます。

1つ目は、ブラウザの開発者ツールを使う方法です。Google Chromeの場合、対象のページを開いた状態でF12キーを押し、「Network」タブを選択します。ページを再読み込みして、最初のHTMLリクエストを選択すると「Response Headers」にセキュリティヘッダーが表示されます。ここに Strict-Transport-SecurityContent-Security-Policy といった項目がなければ、それらは未設定ということです。

2つ目は、SecurityHeaders.comを利用する方法です。自社サイトのURLを入力するだけで、設定済みのヘッダーと不足しているヘッダーをA+からFまでのグレードで判定してくれます。「Missing Headers」として表示される項目が、これから設定すべきヘッダーの候補です。

3つ目は、Mozilla Observatoryを使う方法です。SecurityHeaders.comがヘッダーに特化しているのに対し、ObservatoryはCookie設定やリダイレクト、サブリソース完全性(SRI)なども含めた総合的なセキュリティ評価を行います。両方のツールで診断すれば、より網羅的に自社サイトの状況を把握できます。

診断結果が「A」以上であれば、基本的なヘッダーは適切に設定されています。「C」以下の場合は、この記事で解説する7つのヘッダーを順に設定していくことで、大幅にスコアを改善できます。

Strict-Transport-Security(HSTS)で通信を暗号化に固定する

HTTPSで配信しているサイトであっても、ユーザーがアドレスバーに http:// から始まるURLを入力したり、古いブックマークからHTTPでアクセスしたりすることがあります。Strict-Transport-Security(HSTS)ヘッダーは、ブラウザに対して「このドメインには常にHTTPSで接続せよ」と指示するものです。HSTSの正式な仕様はRFC 6797として標準化されています。

HSTSが設定されたドメインに一度でもアクセスすると、ブラウザは指定された期間(max-age)中、HTTPへのリクエストを自動的にHTTPSにリダイレクトします。これにより、中間者攻撃(Man-in-the-Middle)でHTTP通信を傍受される危険性が大幅に低減されます。

設定例は以下の通りです。

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

max-age=31536000 は1年間(秒単位)を意味します。includeSubDomains はサブドメインにもHSTSを適用する指定で、preload はブラウザのHSTSプリロードリストへの登録を意図するフラグです。preload フラグを付与したうえで hstspreload.org にドメインを登録申請すると、Chrome、Firefox、Safari、Edgeの主要ブラウザに組み込まれたプリロードリストにドメインが追加され、初回アクセスからHTTPSが強制されるようになります。2026年4月時点で、プリロードリストには約30万ドメインが登録されており、主要なWebサービスのほとんどが対応済みです。

HSTSで注意すべきは、一度設定すると max-age の期間中はHTTPへの切り戻しが困難になる点です。まず max-age=300(5分)など短い値でテストし、問題がないことを確認してから段階的に延ばしていくのが安全なアプローチです。プリロードリストへの登録はさらに解除が困難なため、本番運用で十分な実績を積んでから申請してください。

Content-Security-Policy(CSP)でスクリプトの実行を制御する

CSPは、ページ上で実行を許可するリソースの取得元をホワイトリスト方式で指定するヘッダーです。XSS攻撃では、攻撃者がページにスクリプトを注入して実行させますが、CSPが設定されていれば、許可されていないオリジンからのスクリプトはブラウザが実行を拒否します。MDNのCSPドキュメントでは各ディレクティブの詳細な仕様と使用例が網羅されており、W3CのCSP Level 3仕様書で最新の標準仕様を確認できます。

基本的な設定は次の形式です。

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'

default-src 'self' は、特に指定がない種類のリソースはすべて同一オリジンからのみ許可するという基本方針です。script-src でスクリプトの取得元を、style-src でスタイルシートの取得元をそれぞれ限定しています。

ドメインホワイトリスト方式の限界とnonce方式

上記のようなドメインホワイトリスト方式は直感的ですが、許可したドメイン上にオープンリダイレクトやJSONPエンドポイントが存在すると、CSPを迂回される可能性があります。2026年現在、より安全なアプローチとして nonce方式strict-dynamic の活用が推奨されています。

Content-Security-Policy: script-src 'nonce-{ランダム値}' 'strict-dynamic'; base-uri 'self'; object-src 'none'

nonce方式では、サーバーがリクエストごとにランダムな値(nonce)を生成し、HTMLの <script> タグとCSPヘッダーの両方に同じ値を埋め込みます。nonceが一致するスクリプトだけが実行を許可されるため、ドメイン単位の許可よりも厳密な制御が可能です。strict-dynamic を併用すると、許可されたスクリプトが動的に読み込む子スクリプトも自動的に許可されるため、Google Tag Managerのような動的ローダーとも共存できます。

実際のWebサイトではGoogle AnalyticsやGoogleタグマネージャーを利用しているケースが多いため、従来のドメインホワイトリスト方式で始める場合は以下が現実的な出発点になります。

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com; img-src 'self' https://www.google-analytics.com data:; connect-src 'self' https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; font-src 'self' https://fonts.gstatic.com

CSP違反レポートの受信

CSPの導入でよくある失敗は、いきなり厳格なポリシーを本番に適用して、外部チャットウィジェットなどが動かなくなるケースです。まずは Content-Security-Policy-Report-Only ヘッダーを使ってレポートモードで運用し、ブラウザのコンソールに表示される違反レポートを確認しながらポリシーを調整することを強く推奨します。

違反レポートの送信先については、従来の report-uri ディレクティブに代わり、2026年現在は Reporting API v1 が標準化されています。Reporting-Endpoints ヘッダーでエンドポイントを定義し、CSP側で report-to ディレクティブを使用する形式です。

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

CSPは7つのヘッダーの中で最も設定が複雑ですが、XSS攻撃に対する防御効果も最も高いヘッダーです。「まずはレポートモードから始める」という方針で、恐れずに導入を進めてください。

X-Content-Type-Options でMIMEスニッフィングを防ぐ

ブラウザには、サーバーが返すContent-Typeヘッダーの指定を無視して、ファイルの中身を推測(スニッフィング)する機能があります。この機能が悪用されると、たとえば画像としてアップロードされたファイルがスクリプトとして実行されてしまう可能性があります。

X-Content-Type-Options ヘッダーは、この推測を停止させます。

X-Content-Type-Options: nosniff

設定値は nosniff の一択です。設定による副作用はほとんどなく、すべてのWebサイトで有効にすべきヘッダーです。MDNのX-Content-Type-Optionsドキュメントでも、このヘッダーの設定を明確に推奨しています。

ファイルアップロード機能を持つWebアプリケーションでは、このヘッダーの設定が特に重要です。ユーザーがアップロードしたファイルをそのまま配信する場合、サーバー側でContent-Typeを正しく設定した上でX-Content-Type-Optionsも付与することで、MIMEスニッフィングによるスクリプト実行を二重に防止できます。WordPressなどのCMSを利用している場合は、メディアアップロード経由の攻撃にも有効です(WordPressのセキュリティ対策については「週300件超の脆弱性が見つかる時代のプラグイン管理と防御の実務」も参照してください)。

X-Frame-Options / frame-ancestors でクリックジャッキングを阻止する

クリックジャッキングとは、攻撃者が透明なiframeに正規サイトを読み込み、ユーザーに意図しない操作(購入ボタンのクリック、設定変更など)をさせる攻撃手法です。X-Frame-Options ヘッダーは、自サイトが他サイトのiframeに読み込まれることを制限します。

X-Frame-Options: DENY

DENY はすべてのiframe埋め込みを禁止します。自社の別ページでiframeを使う必要がある場合は SAMEORIGIN を指定すると、同一オリジンからの埋め込みのみ許可できます。

なお、X-Frame-Options は古い仕様であり、CSPの frame-ancestors ディレクティブが後継として策定されています。

Content-Security-Policy: frame-ancestors 'self'

現時点ではX-Frame-OptionsとCSP frame-ancestorsの両方を設定しておくのが最も安全です。古いブラウザはCSPのframe-ancestorsに対応していないため、X-Frame-Optionsがフォールバックとして機能します。なお、2026年現在のChrome・Firefox・Safari・Edgeはすべてframe-ancestorsに対応しているため、対象ブラウザがモダンブラウザに限定できるサイトでは、CSP frame-ancestorsのみでも実用上は問題ありません。

Referrer-Policy で意図しない情報漏えいを防ぐ

ユーザーがリンクをクリックしてページを遷移するとき、ブラウザは遷移元のURLをRefererヘッダーとして送信します。このURLにセッションIDや検索クエリ、管理画面のパスといった機密情報が含まれている場合、遷移先のサイトにその情報が漏えいします。

Referrer-Policyヘッダーは、Referer情報をどこまで送信するかを制御します。

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

この設定は、同一オリジン内では完全なURLを送信し、異なるオリジンへはオリジン部分(https://example.com まで)だけを送信し、HTTPSからHTTPへの遷移ではRefererを送信しない、という動作になります。なお、2026年現在の主要ブラウザ(Chrome、Firefox、Safari、Edge)はデフォルトのReferrer-Policyとして strict-origin-when-cross-origin を採用しています。しかし、明示的にヘッダーを設定することで、古いブラウザや設定変更されたブラウザからのアクセスにも確実にポリシーを適用できます。

no-referrer を設定すればRefererの送信を完全に止められますが、Google Analyticsなどのアクセス解析で参照元が「direct」として記録されてしまうため、多くのサイトでは strict-origin-when-cross-origin が現実的な選択肢です。

Permissions-Policy でブラウザ機能の悪用を制限する

Permissions-Policy(旧称 Feature-Policy)は、ブラウザのAPI(カメラ、マイク、位置情報、全画面表示など)の使用をページごとに許可・禁止するヘッダーです。自社サイトでカメラを使う機能がないのにカメラの権限が開いていると、XSSや悪意あるサードパーティスクリプトを通じてカメラが起動される可能性があります。

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=(), browsing-topics=()

camera=() は「どのオリジンにもカメラの使用を許可しない」という意味です。自社オリジンで使用する場合は camera=(self) と記述します。上の例では、カメラ・マイク・位置情報・決済API・USB・Bluetoothの6つのAPIに加え、browsing-topics=() でChromeのTopics API(旧FLoC)によるユーザー興味カテゴリの推定も無効化しています。Topics APIは広告目的のトラッキング技術であり、自社サイトがユーザーの広告プロファイリングに利用されることを防ぐために無効化しておくのが望ましいです。

必要のないブラウザ機能を明示的に無効化することで、仮にXSSが成功した場合でも攻撃者が利用できるAPIを大幅に制限できます。特にECサイトやお問い合わせフォームを持つサイトでは、payment=() の設定によるPayment Request API の制限が有効です。

Cache-Control でキャッシュ経由の情報漏えいを防ぐ

Cache-Controlヘッダーは通常パフォーマンス最適化の文脈で語られますが、セキュリティの観点でも重要な意味を持ちます。ログイン後のマイページや管理画面のレスポンスがプロキシサーバーやブラウザにキャッシュされると、別のユーザーが同じ端末やネットワークから個人情報にアクセスできてしまう危険があります。

機密性の高いページには、以下のヘッダーを設定します。

Cache-Control: no-store, no-cache, must-revalidate, private

no-store はレスポンスをキャッシュに保存しない指示、private は共有キャッシュ(プロキシ)での保存を禁止する指示です。

一方、静的アセット(CSS、JavaScript、画像)には長めのキャッシュを設定するのがパフォーマンスのために望ましいため、URLにハッシュやバージョン番号を含めるキャッシュバスティングの手法と組み合わせるのが一般的です。

セキュリティとパフォーマンスは相反するように見えますが、「機密ページはno-store、静的アセットは長期キャッシュ」と使い分けることで、両立は十分に可能です。MDNのCache-Controlドキュメントには、用途別の推奨設定パターンが詳しく解説されています。

京谷商会での導入事例——Cloudflare Workers で7ヘッダーを一括設定

京谷商会では、自社サイト(kyotanishokai.co.jp)をCloudflare Workers上で運用しています。Workersのミドルウェア機能を使うことで、すべてのレスポンスに対して7つのセキュリティヘッダーを一括で付与しています。なお、京谷商会はこのサイトで1日126万リクエストのボット攻撃をCloudflare無料プランだけで撃退した実績がありますが、そうしたWAF・Bot Management設定とセキュリティヘッダーは「多層防御」として組み合わせることで初めて効果を最大化できます。

導入前にSecurityHeaders.comで診断したところ、グレードは「D」でした。HSTSはCloudflareのSSL設定で自動的に付与されていたものの、CSPやPermissions-Policyは一切設定されておらず、X-Content-Type-OptionsやX-Frame-Optionsも抜けている状態でした。

Workersのミドルウェアであれば、APIルートごとにヘッダーを個別設定する必要がなく、全レスポンスに統一的にヘッダーを付与できるため、設定漏れのリスクが極めて低くなります

導入の手順は以下の3段階で進めました。

まず、CSPをReport-Onlyモードで2週間運用し、Google Analytics、GTM、外部フォントなど実際に読み込まれているサードパーティリソースを洗い出しました。この段階でブロックされるリソースはなく、表示崩れの心配もなかったため、安全に進められました。

次に、洗い出した外部リソースをCSPのホワイトリストに追加し、Report-Onlyを外して本番適用しました。同時に、他の6つのヘッダーも一括で追加しています。

最後に、SecurityHeaders.comで再診断したところ、グレードは「A+」に改善されました。導入に要した期間は約3週間で、そのうち2週間はCSPのReport-Only期間です。実際の設定作業は半日程度で完了しています。

この経験から言えるのは、セキュリティヘッダーの設定はWebサイトのセキュリティ対策の中で最もコストパフォーマンスが高い施策だということです。コード変更は不要で、CDNやリバースプロキシの設定だけで完結し、効果はSecurityHeaders.comのグレードという形で即座に確認できます。

次のステップ——Cross-Origin系ヘッダーへの対応

この記事で紹介した7つのヘッダーに加えて、2026年現在注目すべきヘッダーとして Cross-Origin系ヘッダー があります。

  • Cross-Origin-Opener-Policy(COOP): 自サイトのウィンドウが他オリジンのウィンドウから参照されることを制限
  • Cross-Origin-Embedder-Policy(COEP): 自サイトが読み込むリソースにCORSまたはCORP設定を要求
  • Cross-Origin-Resource-Policy(CORP): 自サイトのリソースが他オリジンから直接読み込まれることを制限

これらは SharedArrayBuffer や高精度タイマーといったAPI利用の前提条件となっており、Spectre対策としても重要です。ただし、サードパーティリソースへの影響が大きいため、まずは上記7つのヘッダーを確実に設定してから段階的に検討するのが現実的です。

来週から始めるアクションプラン

7つのヘッダーをすべて一度に設定する必要はありません。以下の優先順位で、1つずつ確実に導入していくことを推奨します。より包括的なセキュリティ対策については「今日から使える中小企業セキュリティ対策チェックリスト50項目」も活用してください。

最初に取り組むべきは、X-Content-Type-Options の設定です。nosniff の一択で副作用がほぼなく、すべてのWebサーバーで設定可能です。

Apache の場合:

Header set X-Content-Type-Options "nosniff"

Nginx の場合:

add_header X-Content-Type-Options "nosniff" always;

次に、X-Frame-Options を DENY または SAMEORIGIN で設定します。自社サイトをiframeで表示する必要がなければ DENY を選びます。これだけでクリックジャッキング攻撃を防御できます。

3番目に、HSTSを短い max-age で有効化し、問題がなければ徐々に期間を延ばします。すでにHTTPSで運用しているサイトであれば、リスクは最小限です。

4番目以降は、Referrer-Policy、Permissions-Policy、Cache-Control、CSPの順で進めます。CSPは最も効果が高い一方で設定が複雑なため、最後に回して十分な検証時間を確保します。前述のnonce方式と strict-dynamic を採用すれば、ドメインホワイトリストのメンテナンス負荷を大幅に軽減できます。

「来週、SecurityHeaders.comで自社サイトを1回診断する」——この1アクションが、セキュリティヘッダー導入の最も確実な第一歩です。診断結果のスクリーンショットを社内で共有するだけでも、セキュリティ意識の向上につながります。

Webセキュリティの脅威は日々進化していますが、基本的な防御策はそう頻繁に変わりません。HTTPセキュリティヘッダーは、その基本的な防御策の中でも最も手軽に導入でき、効果が明確に測定できる施策です。まずは診断から始めて、自社サイトの「見えない守り」を1つずつ整えていきましょう。