はじめに: 7つのヘッダで防御層を作る
Web アプリの脆弱性対策はコード側だけではありません。HTTP レスポンスヘッダでブラウザに「この挙動は禁止」「この通信ルールに従って」と指示することで、コード側の漏れを補う多層防御が成立します。
本サイト secutils 自身も securityheaders.com で A評価を取得しており、本記事ではその実装例を交えながら主要ヘッダ7つを解説します。無料で、コード変更ほぼゼロで、すぐに導入できるのがセキュリティヘッダの最大の魅力です。
① Content-Security-Policy(CSP)- XSS の最後の砦
最重要のヘッダ。「このページが読み込み・実行できるリソースの出所」をブラウザに宣言します。XSS 対策の本丸が出力時エスケープなのは前提として、もしエスケープが破れた時の最後の砦がこの CSP です。
本サイトの実装例(next.config.ts から抜粋):
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://va.vercel-scripts.com ...;
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob: ...;
font-src 'self' data:;
connect-src 'self' https://vitals.vercel-insights.com ...;
frame-src 'self' ...;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests各ディレクティブの役割:
| ディレクティブ | 意味 |
|---|---|
default-src 'self' | 未指定の他ディレクティブのフォールバック。同一オリジンのみ |
script-src | JavaScript の出所制限。ここが最重要 |
style-src | CSSの出所制限 |
img-src | 画像の出所制限 |
connect-src | fetch/XHR/WebSocketの宛先制限 |
frame-src | iframe で埋め込めるオリジン |
object-src 'none' | Flash等プラグインを完全禁止(推奨) |
base-uri 'self' | <base> タグの改ざん攻撃を防止 |
form-action 'self' | フォーム送信先を自オリジンに限定 |
frame-ancestors 'none' | このページの iframe 埋め込み禁止(クリックジャッキング対策) |
upgrade-insecure-requests | http:// リソースを自動で https:// に書き換え |
CSP の難所: 'unsafe-inline'
本来 CSP の真価は 'unsafe-inline' を排除することにあります。<script>...</script> や onclick="..." のようなインライン JS を全て禁止すると、XSS で script タグを注入されても実行できなくなる。
ただし React/Next.js のようなフレームワークは初期ハイドレーション用に必ずインライン script を出すため、'unsafe-inline' を許可しないと動きません。回避策は2つ:
- nonce 方式: リクエストごとにランダムな nonce を発行、許可されたインライン script にだけ
nonce="..."を付ける。動的レンダリングが必須になり、CDN キャッシュが効かなくなる - hash 方式: 許可するインライン script の SHA256 ハッシュを CSP に書く。スクリプト内容が変わるたびに更新が必要
本サイトは「Vercel 無料枠で静的化を温存」という運用要件から、'unsafe-inline' 許容の構成を選択。代わりに frame-ancestors 'none', object-src 'none', base-uri 'self' など他の防御を厚くしてA評価を取っています。
⚠ A+評価を取るには nonce/hash 方式が必須。「セキュリティ最高ランク」と「静的化による高速 + 低コスト」のトレードオフはサービスの性質で判断します。
② Strict-Transport-Security(HSTS)- HTTPS 強制
ブラウザに「このサイトは今後 HTTPS でしか接続するな」と命令するヘッダ。MITM 攻撃や HTTP→HTTPS リダイレクトの隙間を突く攻撃を防ぎます。
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload| パラメータ | 意味 |
|---|---|
max-age=63072000 | 2年間(秒数)。ブラウザがこのサイトをHTTPS強制と覚える期間 |
includeSubDomains | サブドメインも HTTPS 必須にする |
preload | hstspreload.org 経由でブラウザにバンドルされる宣言 |
重要な注意:HSTS を設定するとロールバック困難です。max-age が長期間(2年)の間、ブラウザは強制的に HTTPS を使うので、間違えて全サブドメインに includeSubDomains を効かせると、HTTP 専用の社内ツールが繋がらなくなる事故が起きえます。本番投入前に短い max-age で慣らし、徐々に伸ばすのが鉄則。
③ X-Frame-Options - クリックジャッキング対策
他サイトの iframe にこのページを埋め込まれることを防ぎます。クリックジャッキング(透明な iframe を上に重ねてユーザーに気付かせず操作させる攻撃)対策。
X-Frame-Options: DENY値の選択肢:
DENY: 全てのサイトから iframe 埋め込み禁止(推奨)SAMEORIGIN: 同一オリジンのみ iframe 埋め込み許可ALLOW-FROM uri: 特定オリジンを許可(廃止予定、CSP のframe-ancestorsを使う)
X-Frame-Options と CSP の frame-ancestors は機能的に重複しており、現代では CSP 側が主流。ただし古いブラウザ互換のために両方設定するのが慣例で、本サイトも両方入れています。
④ X-Content-Type-Options - MIME スニッフィング無効化
X-Content-Type-Options: nosniffブラウザは時として「サーバが返した Content-Type を信用せず、内容から型を推測する」MIME スニッフィングを行います。これが脆弱性につながります:
- サーバが画像 (
image/png) として返したファイルが、内容に JS が混入していると、ブラウザが「これは JS だ」と判断して実行 - ユーザーがアップロードした画像が実は JS で、攻撃成立
nosniff を付けると「Content-Type を信じる、推測しない」挙動になり、この攻撃面が消えます。無設定で困ることはまずないので、必ず付けるべきヘッダ。
⑤ Referrer-Policy - リファラ漏洩制御
外部サイトに遷移した時に Referer ヘッダで「どこから来たか」をどこまで伝えるかを制御します。プライバシーと機能性のバランスが論点。
Referrer-Policy: strict-origin-when-cross-origin主な値:
| 値 | 挙動 |
|---|---|
no-referrer | 常にRefererを送らない(最強プライバシー、Analyticsで参照元不明に) |
strict-origin-when-cross-origin | 同一オリジンならフルパス、別オリジンならオリジンのみ。現代ブラウザ既定かつ推奨 |
same-origin | 別オリジンには一切送らない |
unsafe-url | 常にフルURLを送る(避けるべき) |
URL にトークンやセッション ID が入る可能性があるなら、厳格な値にしてリファラ経由の漏洩を防ぐのが基本。
⑥ Permissions-Policy - ブラウザAPI制限
旧称 Feature-Policy。「カメラ・マイク・位置情報など機微なAPIを、このサイト/iframeから使用可能にするか」を宣言します。
Permissions-Policy:
camera=(),
microphone=(),
geolocation=(),
browsing-topics=(),
interest-cohort=(),
payment=(),
usb=()()(空)は「どこからも使用不可」の意味。本サイトは静的ツール集なので、これらのAPIを一切必要としないので全部閉じています。
特に注目すべき項目:
browsing-topics=()/interest-cohort=(): Google が推進した広告ターゲティング技術(Topics API / FLoC)を無効化。プライバシー視点では推奨camera=()/microphone=(): 不要なら必ず無効化。XSS された時に勝手にカメラを起動される攻撃を防ぐ
⑦ X-DNS-Prefetch-Control - DNSプリフェッチ
X-DNS-Prefetch-Control: onページ内のリンク先ホスト名の DNS 解決を、ユーザーがクリックする前にブラウザに先回りさせる設定。セキュリティではなく速度のためのヘッダですが、securityheaders.com の評価項目に含まれているので合わせて設定します。
プライバシー重視なら off もあり(DNS クエリで興味関心が漏れる懸念)。本サイトは外部リンクが少ないので on でデフォルトの体験を優先しています。
「設定しない」べきヘッダもある
X-XSS-Protection(廃止)
昔は X-XSS-Protection: 1; mode=block が推奨されていましたが、ブラウザ側のヒューリスティックが脆弱性を生むことが判明し、Chromeは2020年に削除。無くてOK、CSPで防御。
Server / X-Powered-By
サーバ実装情報を漏らすヘッダ(Server: nginx/1.18.0 など)。攻撃者にバージョン依存の脆弱性を狙う手がかりを与えるので、削除するのがベストプラクティス。Next.js は poweredByHeader: false で明示的に切れます。
Cookie のセキュリティ属性も合わせて
ヘッダ群とは別ですが、Cookie のセキュリティ属性も同じレイヤーで対策します。詳しくは HTTP Cookie Parser ツールで属性可視化できますが、要点は3つ:
Secure: HTTPS でのみ送信HttpOnly: JS から読めない(XSS での Cookie 窃取を防止)SameSite=Lax(またはStrict): クロスサイトでの自動送信を制限(CSRF対策)
導入手順とテスト
どこに書くか:
- Next.js:
next.config.tsのheaders()で - Express: helmet ミドルウェア
- Nginx / Apache: 各設定ファイルで
add_header/Header set - Cloudflare / Vercel / Netlify: ダッシュボード or 設定ファイル
テストは2ステップ:
- securityheaders.com でグレード確認(A以上が目安)
- CSP Evaluator(Google)で CSP の弱点をピンポイント分析
どちらも無料。設定変更のたびにチェックする習慣を付けると、CSP デプロイ事故が減ります。
段階的導入のコツ
いきなり厳格なCSPを本番投入すると、サイトが壊れて顧客に迷惑をかける可能性があります。Report-Only モードから始めるのが定石:
Content-Security-Policy-Report-Only: ...このヘッダはブロックせずに違反だけレポートさせる。1〜2週間運用してログを見て、本来許可すべきリソースを特定してから本番モードに切り替えます。
HSTS も同様に、max-age を最初は短く(数時間 → 数日 → 数ヶ月 → 2年)と段階的に伸ばすのが安全。
まとめ: 最小構成のテンプレート
新規サイトの初期設定として、最低限これを入れれば securityheaders.com で A評価を狙えます:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
object-src 'none';
base-uri 'self';
frame-ancestors 'none'
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()7行のヘッダ追加で、XSS / クリックジャッキング / MIMEスニッフィング / リファラ漏洩 / 機微API濫用 / HTTPダウングレード 全てに対する基礎防御が成立します。
おわりに
セキュリティヘッダは「コード変更ほぼゼロで A 評価が取れる」コスパ最強の対策です。OWASP Top 10 の A05(Security Misconfiguration)を一発で改善できる、見過ごせない打ち手。
本サイトの HTTP Status Code Reference や HTTP Cookie Parser で関連ヘッダの動作を確認できます。設定後は securityheaders.com でグレードチェックする習慣を付けてください。
関連: XSS の基礎と防御 / CSRF の仕組みと対策 / HTTPS と TLS の仕組み