セキュリティヘッダーの設定方法:X-Frame-Options・nosniff・Referrer-Policy・Permissions-Policy
執筆:IDEAVALU運営 · 更新:
レスポンスヘッダーを数行足すだけで、ブラウザ側の防御を有効にできます。多くの個人開発サイトで未設定のまま公開されている項目です。
各ヘッダーの役割
それぞれ、防いでいるものが違います。
- X-Frame-Options(または CSP の frame-ancestors):他のサイトに透明な iframe で埋め込まれ、ボタンを押させられる「クリックジャッキング」を防ぎます。
- X-Content-Type-Options: nosniff:ブラウザがファイルの種類を推測して、画像などをスクリプトとして実行するのを防ぎます。
- Referrer-Policy:リンク先へ送る URL の範囲を決めます。strict-origin-when-cross-origin なら、外部サイトにはドメインだけが送られ、URL に含まれる ID やトークンが漏れにくくなります。
- Permissions-Policy:カメラ・マイク・位置情報など、使わないブラウザ機能を無効にします。埋め込んだ外部スクリプトが勝手に使うのを防げます。
自分で確認する方法
次のコマンドで、主なヘッダーをまとめて表示できます。
主なセキュリティヘッダーを表示する
curl -sI https://example.com | grep -iE "x-frame-options|x-content-type-options|referrer-policy|permissions-policy|content-security-policy|strict-transport-security"
バージョン表示と security.txt
Server や X-Powered-By ヘッダーに「nginx/1.18.0」「PHP/7.4」のようなバージョンが出ていると、古い版の既知の脆弱性を狙う手がかりになります。表示を消し、ソフトウェア自体も更新してください。
/.well-known/security.txt に連絡先を書いておくと、脆弱性を見つけた人が報告先に迷いません(RFC 9116)。最低限 Contact と Expires の2行を書きます。
public/.well-known/security.txt の例
Contact: mailto:security@example.com Expires: 2027-12-31T23:59:59.000Z Preferred-Languages: ja, en
直し方
クリックジャッキング対策
X-Frame-Options(または CSP の frame-ancestors)で、他サイトへの埋め込みを禁止します。
Next.js の場合
// next.config.mjs
const securityHeaders = [
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
]
export default {
async headers() {
return [{ source: '/:path*', headers: securityHeaders }]
},
}Vercel で静的サイト・Vite などを公開している場合
// vercel.json(Next.js 以外を Vercel で公開している場合)
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains" },
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}Netlify・Cloudflare Pages の場合
# public/_headers(Netlify・Cloudflare Pages) /* Strict-Transport-Security: max-age=63072000; includeSubDomains X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: camera=(), microphone=(), geolocation=()
1つの設定で HSTS・クリックジャッキング・nosniff・Referrer-Policy・Permissions-Policy をまとめて直せます。カメラや位置情報を使うアプリは、Permissions-Policy の該当機能を self に変えてください。
X-Content-Type-Options
X-Content-Type-Options: nosniff を付けます。設定例は上と同じです。
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin を付けると、外部サイトにはドメインだけが送られます。設定例は上と同じです。
Permissions-Policy
使わないブラウザ機能を Permissions-Policy で無効にします。設定例は上と同じです。
ソフトウェアのバージョン表示
レスポンスヘッダーからバージョン番号を消します。
nginx の場合
server_tokens off;
Express の場合
app.disable('x-powered-by')PHP の場合(php.ini)
expose_php = Off
よくある質問
- X-Frame-Options と frame-ancestors はどちらを使えばよいですか?
- 新しいブラウザは CSP の frame-ancestors を優先します。CSP を使っていない場合は X-Frame-Options: SAMEORIGIN を付けておけば十分です。両方付けても問題ありません。