セキュリティ対策で指定すべきとされているHTTPヘッダーとして、以下のものがよく知られています。
- X-XSS-Protection
 - X-Content-Type-Options
 - Strict-Transport-Security
 - X-Frame-Options
 - Content-Security-Policy
 
世の中の大規模サービスがこれらのヘッダーをどう設定しているのか気になったので調べてまとめました。Content-Security-Policyについては設定値が長いのでヘッダーの有無だけを記載しています。
| HTTPヘッダー | Github | Netflix | Slack | ||
|---|---|---|---|---|---|
| X-XSS-Protection | 0 | 1; mode=block | 1; mode=block | 1; mode=block | 1; mode=block | 
| X-Content-Type-Options | nosniff | nosniff | nosniff | nosniff | nosniff | 
| Strict-Transport-Security | max-age=15552000; preload  | 
max-age=631138519 | max-age=31536000; includeSubdomains; preload  | 
max-age=31536000 | max-age=31536000; includeSubDomains; preload  | 
| X-Frame-Options | DENY | SAMEORIGIN | DENY | DENY | SAMEORIGIN | 
| Content-Security-Policy | あり | あり | あり | なし | なし | 
X-XSS-Protection
ブラウザのXSSフィルターを有効化/無効化するためのヘッダー。
設定値は1; mode=blockとし、XSSフィルターを有効化かつXSS検出時にページのレンダリングを停止させるのが定石です(mode=blockを指定しない場合、ページをサニタイズした上でレンダリングが続行されます)。
Facebookは唯一XSSフィルターを無効化していますが、その分後述のContent-Secirity-Policyを厳密に定義しアプリケーション側の対策を十分に行なっているということだと思われます。
また、表ではスペースの都合上省略していますが、TwitterとNetflixではXSSが検出されたときにページの情報をサーバーに送信するオプションを指定しています。
X-XSS-Protection: 1; mode=block; report=https://twitter.com/i/xss_reportX-Content-Type-Options
ブラウザがファイルの中身からContentTypeを決める機能(sniffing)を無効化し、常にレスポンスヘッダのContentTypeが優先されるよう指示するヘッダー(XSS対策)。
上記の全てのサービスでnosniffを指定しています。
Strict-Transport-Security
HTTPSでのアクセスを強制するヘッダー。初回のHTTPSアクセス後、max-ageに指定された時間(秒)の間はHTTPSによりリクエストが行われるようになります(HTTPリクエストもHTTPSリクエストに変換される)。
上記のすべてのサービスで、十分に長い時間をmax-ageに指定してHTTPSでのアクセスを強制しています。GithubとSlackはincludeSubdomainを指定してこのポリシーをサブドメインにも適用しています。
preloadについては以下を参照。
https://developer.mozilla.org/ja/docs/Web/Security/HTTP_Strict_Transport_Security#Preloading_Strict_Transport_Security
X-Frame-Options
フレーム(frameまたはiframeタグ)内でページの表示を許可するか/しないかを指定するヘッダー(クリックジャッキング対策)。
DENY(一切禁止)とするか、SAMEORIGIN(同一ドメインのみ許可)とするかの選択です。
Content-Security-Policy (CSP)
jsやcssなどのコンテンツの取得元ドメインを制限するためのヘッダー(XSS対策)。metaタグでも指定可能です。
大規模サービスだと、複数のドメインを持っていたりCDNを多用していたりでコレの記述はめちゃくちゃ細かいです。Githubの場合はこんな感じです。
Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com; worker-src 'self'
NetflixとSlackではこのヘッダがありませんでした。metaタグでの指定もなかったのでCSPの設定は行なっていないということでしょうか(?)