HTTPQUERY
日本語

X-Content-Type-Options

使い方

MIME スニッフィングは、ブラウザがレスポンスの内容を検査し、レスポンスボディに見つかったパターンに基づいて宣言された Content-Type を上書きするブラウザの挙動です。設定が誤ったサーバーへの便宜として意図されたものですが、MIME スニッフィングはセキュリティ上の穴を開けます。攻撃者が画像に偽装したファイルをアップロードし、ブラウザがその内容を HTML や JavaScript としてスニッフィングすると、クロスサイトスクリプティング攻撃が実行されてしまいます。

X-Content-Type-Options ヘッダーはこの穴を塞ぎます。nosniff に設定すると、ブラウザは Content-Type ヘッダーに厳密に従い、宣言された型が期待される型と一致しないリソースの読み込みを拒否します。スタイルの宛先では、Content-Type が text/css でない限りブラウザはレスポンスをブロックします。スクリプトの宛先では、Content-Type が有効な JavaScript の MIME タイプでない限りブラウザはレスポンスをブロックします。

このヘッダーは標準的なセキュリティ強化策として広く導入されており、多層防御のために Content-Security-Policy や X-Frame-Options と併せて利用することが推奨されます。

nosniff

nosniff は定義されている唯一の値です。このディレクティブを設定すると、ブラウザが宣言された Content-Type から逸脱してレスポンスを MIME スニッフィングすることを防げます。

例

MIME スニッフィングを無効化して JSON API のレスポンスを配信するサーバーです。ブラウザがレスポンスを厳密に JSON として扱うようにします。

Content-Type: application/json
X-Content-Type-Options: nosniff

正しい Content-Type とスニッフィング防止を伴って配信される CSS ファイルです。ブラウザがファイルを再解釈するのを防ぎます。

Content-Type: text/css
X-Content-Type-Options: nosniff

トラブルシューティング

nosniff によってブロックされたリソースは、宣言された Content-Type とリソースの宛先に期待される型との MIME タイプの不一致を指摘するコンソールエラーを出力します。

MIME タイプの不一致でスクリプトがブロックされる。ブラウザは Refused to execute script from ’…’ because its MIME type (‘text/plain’) is not executable というログを出します。これは、サーバーが JavaScript ファイルを有効な JavaScript の MIME タイプ(text/javascript、application/javascript)以外の Content-Type で送っている場合に発生します。サーバーの設定を修正してください。nginx では http ブロックに include mime.types; があることを確認します。Apache では設定ファイルまたは .htaccess に AddType text/javascript .js があることを確認します。

nosniff と誤った MIME タイプにより CSS が適用されない。コンソールには Refused to apply style from ’…’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type と表示されます。サーバーが CSS ファイルを text/css ではなく text/html や text/plain として送っています。nginx では types { text/css css; } を追加するか、既定の mime.types ファイルを読み込むことで不一致が解消します。Apache ではサーバー設定に AddType text/css .css を追加します。

サーバーが静的ファイルに誤った Content-Type を送る。設定が誤ったサーバー、CDN、オブジェクトストレージ(S3、GCS)は、静的ファイルを application/octet-stream や text/plain として配信することがよくあります。DevTools の Network タブでリクエストを選択してレスポンスヘッダーを確認し、各リソースの Content-Type を調べてください。S3 ではアップロード時に ContentType のメタデータを設定します。CDN から配信されるアセットについては、ほとんどの CDN がオリジンの Content-Type をそのまま通すため、オリジンが正しい型を返していることを確認してください。

DevTools の Console でブロックされたリソースを診断する。Console タブを開き、MIME 関連のエラーでフィルタリングします。ブロックされた各リソースのメッセージには、URL、宣言された MIME タイプ、期待される型が含まれます。Network タブと突き合わせてください。ブロックされたリクエストを選び、Headers パネルを開いて Content-Type レスポンスヘッダーを確認します。修正は常にサーバー側で Content-Type を正すことであり、nosniff ヘッダーを外すことではありません。

設定

すべてのレスポンスに nosniff を適用してください。オーバーヘッドはごくわずかで、保護はスクリプト、スタイル、その他のサブリソースに及びます。

nginx:

add_header X-Content-Type-Options nosniff always;

Apache:

Header always set X-Content-Type-Options nosniff

IIS(web.config):

<code class="language-xml"><customHeaders>
  <add name="X-Content-Type-Options"
       value="nosniff" />
</customHeaders>