MIMEスニッフィング

現行標準 — 最終更新

参加方法:
GitHub whatwg/mimesniff (新しいIssue, オープン中のIssue)
Matrixでチャット
コミット履歴:
GitHub whatwg/mimesniff/commits
このコミット時点のスナップショット
@mimesniff
テスト:
web-platform-tests mimesniff/ (継続中の作業)
翻訳 (参考資料):
日本語
简体中文
한국어

概要

MIMEスニッフィング標準は、リソースのスニッフィング方法を定義します。

1. はじめに

HTTPのContent-Typeヘッダー・フィールドは、HTTPレスポンスのMIMEタイプを示すことを意図しています。 しかし、多くのHTTPサーバーは、Content-Typeヘッダー・フィールドの値が、実際のレスポンス内容と一致していません。 歴史的に、Webブラウザーはこれらのサーバーに対応するため、HTTPレスポンスの内容をContent-Typeヘッダー・フィールドと併せて調査し、レスポンスの実効MIMEタイプを判定してきました。

MIMEタイプの「スニッフィング」方法に関する明確な仕様がないため、各ユーザーエージェントは他のユーザーエージェントのアルゴリズムをリバースエンジニアリングすることを余儀なくされ、相互運用性を維持しようとしてきました。 当然ながら、これらの試みは完全には成功せず、ユーザーエージェント間で異なる挙動が生じています。 場合によっては、こうした挙動の違いがセキュリティ上の問題を引き起こし、ユーザーエージェントがサーバーの意図と異なるMIMEタイプでHTTPレスポンスを解釈することがありました。

これらのセキュリティ問題は、「正直な」サーバーが悪意ある利用者にファイルのアップロードを許し、その内容を低権限のMIMEタイプで配信する場合に特に深刻です。 例えば、サーバーがアップロードされたファイルを画像として扱う(したがって無害とみなす)と信じていても、ユーザーエージェントがその内容をHTMLと判断し(結果として含まれるスクリプトを実行できる)、攻撃者がユーザーの認証情報を盗んだり、クロスサイトスクリプティング攻撃を仕掛けたりする可能性があります。 (悪意あるサーバーは、もちろんContent-Typeヘッダー・フィールドに任意のMIMEタイプを指定できます。)

この文書では、ユーザーエージェントの互換性ニーズと既存Webコンテンツがもたらすセキュリティ制約とのバランスを慎重に考慮したコンテンツスニッフィング・アルゴリズムについて説明します。 このアルゴリズムは、Adam Barth、Juan Caballero、Dawn Songによる調査に基づいており、主要なユーザーエージェントに実装されたコンテンツスニッフィング・アルゴリズム、既存Webコンテンツの広範なデータベース、および多数のユーザーに展開された実装から収集されたメトリクスが活用されています。 [SECCONTSNIFF]

2. 適合性要件

本文書中の "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY"、"OPTIONAL" というキーワードは、RFC 2119の定義に従い解釈されます。 可読性のため、これらのキーワードは通常すべて大文字では記載しません。 [KEYWORDS]

アルゴリズムの一部として命令形で記述された要件(例:"先頭の空白文字を除去する" や "偽を返してこれらの手順を中止する")は、アルゴリズムの導入に使用されたキーワードの意味で解釈されます。

アルゴリズムや特定の手順として記述された適合性要件は、最終的な結果が同等であればどのような方法で実装しても構いません。 特に、本仕様で定義されたアルゴリズムは理解しやすさを重視しており、性能を重視しているわけではないことに留意してください。

3. 用語

本仕様はInfra標準に依存しています。[INFRA]

HTTPトークンコードポイントは、U+0021 (!)、U+0023 (#)、U+0024 ($)、U+0025 (%)、 U+0026 (&)、U+0027 (')、U+002A (*)、U+002B (+)、U+002D (-)、U+002E (.)、U+005E (^)、U+005F (_)、 U+0060 (`)、U+007C (|)、U+007E (~)、または ASCII英数字です。

これは token トークン生成規則の値空間と一致します。[HTTP-SEMANTICS]

HTTP引用文字列トークンコードポイントは、U+0009 TAB、範囲U+0020 SPACE〜U+007E (~)のコードポイント、または範囲U+0080〜 U+00FF (ÿ)のコードポイントです。

これは quoted-string トークン生成規則の有効な値空間に一致します。定義上、HTTPトークンコードポイントの上位集合です。[HTTP-SEMANTICS]

バイナリデータバイトは、 バイトが0x00〜0x08 (NUL〜BS)、0x0B (VT)、0x0E〜0x1A (SO〜SUB)、 または0x1C〜0x1F (FS〜US)の範囲にあるものです。

空白バイト (略称0xWS)は、以下のいずれかの バイトです:0x09 (HT)、0x0A (LF)、0x0C (FF)、0x0D (CR)、 0x20 (SP)。

タグ終端バイト (略称0xTT)は、以下のいずれかの バイトです:0x20 (SP)、0x3E (">")。

式中の演算子は[ENCODING]で定義されている数学演算子を使用します。加えて、ビット単位のNOTは ~ で表されます。

4. MIMEタイプ

4.1. MIMEタイプの表現

MIMEタイプは、 インターネットメディアタイプMultipurpose Internet Mail Extensions (MIME) Part Two: Media Typesで定義)を表現します。また、MIMEタイプレコードとも呼ばれます。[MIMETYPE]

標準類は混乱を避けるために、一貫してMIMEタイプという用語を使用することが推奨されます。これはMedia Queriesで記述されるメディアタイプの使用と混同しないためです。 [MEDIAQUERIES]

MIMEタイプtypeは、空でない ASCII文字列です。

MIMEタイプsubtypeは、空でない ASCII文字列です。

MIMEタイプparametersは、 順序付きマップであり、キーASCII文字列文字列であり、 HTTP引用文字列トークンコードポイントに制限されています。初期値は空です。

4.2. MIMEタイプ その他

MIMEタイプmimeType本質は、 mimeTypetype、U+002F(/)、mimeTypesubtypeの順で構成されます。

MIMEタイプは、ユーザーエージェントがサポートする場合、 ユーザーエージェントがそのリソースを解釈し、ユーザーに提示できる機能を持つことを意味します。

理想的には、より厳密に記述すべきです。w3c/preload #113

ユーザーエージェントがサポートするMIMEタイプを最小化するには、MIMEタイプmimeTypeを受け取り、以下の手順を実行します。返す値はASCII文字列です。

  1. mimeTypeJavaScript MIMEタイプなら、"text/javascript"を返す。

  2. mimeTypeJSON MIMEタイプなら、"application/json"を返す。

  3. mimeType本質が"image/svg+xml"なら、"image/svg+xml"を返す。

    SVGは他のXML MIMEタイプと区別する価値があります。

  4. mimeTypeXML MIMEタイプなら、"application/xml"を返す。

  5. mimeTypeユーザーエージェントがサポートするなら、mimeType本質を返す。

  6. 空文字列を返す。

このアルゴリズムの目的は、GIFとPNGなど処理モデルが異なるMIMEタイプを識別できるようにすることですが、それ以外は可能な限り情報を少なくすることです。

4.3. MIMEタイプの記述

有効なMIMEタイプ文字列は、 media-typeトークン生成規則に一致する文字列です。特に、有効なMIMEタイプ文字列parametersを含むことがあります。[HTTP-SEMANTICS]

有効なMIMEタイプ文字列は、適合性チェッカーのみで使用することが想定されています。

"text/html"は有効なMIMEタイプ文字列です。

"text/html;"は有効なMIMEタイプ文字列ではありませんが、 MIMEタイプの構文解析は、入力が"text/html"の場合と同じMIMEタイプレコードを返します。

パラメータなしの有効なMIMEタイプ文字列は、 U+003B(;)を含まない有効なMIMEタイプ文字列です。

4.4. MIMEタイプの構文解析

MIMEタイプの構文解析を行うには、文字列inputを受け取り、以下の手順を実行する:

  1. inputの先頭および末尾のHTTP 空白を削除する。

  2. positioninput位置変数とし、最初はinputの先頭を指す。

  3. typeを、positionを指定してinputからU+002F (/) ではないコードポイントの並びを収集した結果とする。

  4. typeが空文字列であるか、HTTPトークンコードポイントのみで構成されていない場合、失敗を返す。

  5. positioninputの末尾を越えている場合、失敗を返す。

  6. positionを1進める。(U+002F (/) を飛ばす。)

  7. subtypeを、positionを指定してinputからU+003B (;) ではないコードポイントの並びを収集した結果とする。

  8. subtypeの末尾からHTTP空白を削除する。

  9. subtypeが空文字列であるか、HTTPトークンコードポイントのみで構成されていない場合、失敗を返す。

  10. mimeTypeを新しいMIMEタイプレコードとし、typetypeASCII小文字で、subtypesubtypeASCII小文字とする。

  11. positioninputの末尾を越えていない間、以下を繰り返す:

    1. positionを1進める。(U+003B (;) を飛ばす。)

    2. positionを指定してinputからHTTP空白並びを収集する。

      これはASCII空白のスキップに概ね相当するが、HTTP空白を使用し、ASCII空白ではない。

    3. positionを指定してinputからU+003B (;) または U+003D (=) ではないコードポイントの並びを収集し、parameterNameとする。

    4. parameterNameASCII小文字にする。

    5. positioninputの末尾を越えていない場合:

      1. positioninput内のコードポイントがU+003B (;) ならば、続行する。

      2. positionを1進める。(U+003D (=) を飛ばす。)

    6. positioninputの末尾を越えている場合、中断する。

    7. parameterValueをnullとする。

    8. positioninput内のコードポイントがU+0022 (") ならば:

      1. parameterValueに、positionとtrueを指定しinputからHTTP引用文字列を収集した結果を設定する。

      2. positionを指定してinputからU+003B (;) ではないコードポイントの並びを収集する。

        例: text/html;charset="shift_jis"iso-2022-jpの場合、text/html;charset=shift_jisとなる。

    9. それ以外の場合:

      1. positionを指定してinputからU+003B (;) ではないコードポイントの並びを収集し、parameterValueとする。

      2. parameterValueの末尾からHTTP空白を削除する。

      3. parameterValueが空文字列ならば、続行する。

    10. すべて以下が真なら:

      その場合、設定する mimeTypeparameters[parameterName] を parameterValueに。

  12. mimeTypeを返す。


バイト列からMIMEタイプを構文解析するには、バイト列inputを受け取り、 以下の手順を実行する:

  1. stringinput等価デコードしたものとする。

  2. stringMIMEタイプを解析する結果を返す。

4.5. MIMEタイプの直列化

MIMEタイプを直列化するには、MIMEタイプ mimeTypeが与えられたとき、次の手順を実行する:

  1. serializationmimeTypetype、U+002F (/)、mimeTypesubtypeを連結したものとする。

  2. namevaluemimeTypeparametersから取り出し:

    1. serializationにU+003B (;)を追加する。

    2. serializationnameを追加する。

    3. serializationにU+003D (=)を追加する。

    4. valueHTTPトークンコードポイントのみで構成されていない、またはvalueが空文字列の場合:

      1. value内のU+0022 (")またはU+005C (\)の各出現の前にU+005C (\)を付ける。

      2. valueの先頭にU+0022 (")を付加する。

      3. valueの末尾にU+0022 (")を付加する。

    5. serializationvalueを追加する。

  3. serializationを返す。


MIMEタイプをバイト列に直列化するには、MIMEタイプ mimeTypeが与えられたとき、次の手順を実行する:

  1. stringSerializationmimeTypeMIMEタイプを直列化する結果とする。

  2. stringSerialization等価エンコードしたものを返す。

4.6. MIMEタイプグループ

画像MIMEタイプは、MIMEタイプであり、そのtypeが"image"であるもの。

音声または動画MIMEタイプは、MIMEタイプであり、typeが"audio"または"video"であるもの、またはessenceが"application/ogg"であるもの。

フォントMIMEタイプは、MIMEタイプであり、typeが"font"であるもの、またはessenceが下記いずれかであるもの:[RFC8081]

ZIPベースMIMEタイプは、MIMEタイプであり、subtypeが"+zip"で終わるもの、またはessenceが下記いずれかであるもの:

アーカイブMIMEタイプは、MIMEタイプであり、essenceが下記いずれかであるもの:

XML MIMEタイプは、MIMEタイプであり、subtypeが"+xml"で終わるもの、またはessenceが"text/xml"または"application/xml"であるもの。[RFC7303]

HTML MIMEタイプは、MIMEタイプであり、essenceが"text/html"であるもの。

スクリプト可能MIMEタイプは、XML MIMEタイプHTML MIMEタイプ、またはMIMEタイプでありessenceが"application/pdf"であるもの。

JavaScript MIMEタイプは、MIMEタイプであり、essenceが下記いずれかであるもの:

文字列は、JavaScript MIMEタイプessence一致であり、ASCII大文字小文字無視JavaScript MIMEタイプessence文字列のいずれかと一致する場合。

このフックは type 属性や script 要素で使用される。[HTML]

JSON MIMEタイプは、MIMEタイプであり、subtypeが"+json"で終わるもの、またはessenceが"application/json"または"text/json"であるもの。

5. リソースの取り扱い

リソースとは ...。

ユーザーエージェントは、取り扱う各リソースについて、次の関連メタデータを管理しなければならない:

5.1. リソースメタデータの解釈

リソース指定MIMEタイプは、そのリソースに関連する外部ソースからユーザーエージェントに提供される。 この情報の取得方法は、リソースの取得方法により異なる。

リソース指定MIMEタイプを決定するには、ユーザーエージェントは以下の指定MIMEタイプ検出アルゴリズムを用いなければならない:

  1. supplied-typeをnullとする。
  2. リソースがHTTP経由で取得された場合、以下を実行する:
    1. 一つ以上のContent-Typeヘッダーがリソースに関連付けられている場合、以下を実行する:
      1. supplied-typeに、リソースに関連付けられている最後のContent-Typeヘッダーの値を設定する。

        ファイル拡張子は、HTTP経由で取得されたリソース指定MIMEタイプの決定には使用しない。これは信頼性が低く、容易に偽装可能であるためである。

      2. supplied-typeが下記の値のいずれかと完全一致する場合、Apacheバグ確認フラグを設定する:
        16進数のバイト値 ASCIIのバイト値
        74 65 78 74 2F 70 6C 61 69 6E text/plain
        74 65 78 74 2F 70 6C 61 69 6E
        3B 20 63 68 61 72 73 65 74 3D
        49 53 4F 2D 38 38 35 39 2D 31
        text/plain; charset=ISO-8859-1
        74 65 78 74 2F 70 6C 61 69 6E
        3B 20 63 68 61 72 73 65 74 3D
        69 73 6F 2D 38 38 35 39 2D 31
        text/plain; charset=iso-8859-1
        74 65 78 74 2F 70 6C 61 69 6E
        3B 20 63 68 61 72 73 65 74 3D
        55 54 46 2D 38
        text/plain; charset=UTF-8

        指定MIMEタイプ検出アルゴリズムは、これらの正確なバイト列を検出する。これは、古いApacheの一部インストールにバグがあり、認識できないMIMEタイプのファイルを提供する際にこれらのContent-Typeヘッダーを返すためである。

    [HTTP-SEMANTICS]

  3. リソースがファイルシステムから直接取得された場合、supplied-typeにファイルシステムが提供したMIMEタイプを設定する。
  4. リソースが他のプロトコル(FTPなど)経由で取得された場合、supplied-typeにそのプロトコルで決定されたMIMEタイプを設定する(該当する場合)。

    [FTP]

  5. supplied-typeMIMEタイプでない場合、指定MIMEタイプは未定義とする。

    これらの手順を中止する。

  6. 指定MIMEタイプsupplied-typeとする。

5.2. リソースヘッダーの読み取り

リソースヘッダーは、バイト列であり、リソースの先頭部分として、リソースヘッダーを読み取るによって定義される。

リソースヘッダーを読み取るには、次の手順を実行する:

  1. bufferバイト列とする。
  2. バイトリソースからbufferに読み込む。次のいずれかの条件を満たすまで繰り返す:
    • リソースの終端に到達した場合。
    • bufferバイト数が1445以上になった場合。
    • ユーザーエージェントが判断する合理的な時間が経過した場合。

    bufferバイト数が1445以上の場合、MIMEタイプスニッフィングアルゴリズムは大多数のケースで決定的となる。

    ただし、回線が遅いなどの理由で、ユーザーエージェントが合理的な時間で1445バイトを読み取れない場合もある。

  3. リソースヘッダーbufferとする。

リソースヘッダーは、各リソースごとに一度だけ決定すればよい。

6. MIMEタイプパターンの照合

バイトパターンは、バイト列であり、パターンマッチングアルゴリズムにおいて照合用テンプレートとして使われる。

パターンマスクは、バイト列であり、バイトバイトパターンとの比較でどれだけ重要かを パターンマッチングアルゴリズムで決定するために使用する。

パターンマスクでは、0xFFはバイトが厳密に重要であること、0xDFはバイトがASCIIの大文字小文字無視で重要であること、0x00はバイトが重要でないことを示す。

特定のバイト列が所定のバイトパターンに一致するかどうかは、以下のパターンマッチングアルゴリズムで判定する。これは、バイト列 inputバイトパターン patternパターンマスク mask、無視する集合バイト ignored を受け取り、trueまたはfalseを返す。

  1. Assert: pattern長さmask長さと等しい。

  2. input長さpattern長さ未満なら、falseを返す。

  3. sを0とする。

  4. s < input長さの間、繰り返す:

    1. ignored含まない input[s]なら、 breakする。

    2. ss + 1にする。

  5. pを0とする。

  6. p < pattern長さの間、繰り返す:

    1. maskedDatainput[s]とmask[p]にビットAND演算子を適用した結果とする。

    2. maskedDatapattern[p]と等しくない場合、falseを返す。

    3. ss + 1にする。

    4. pp + 1にする。

  7. trueを返す。

6.1. 画像タイプパターンの照合

どの画像MIMEタイプバイトパターンバイト列inputが一致するか(該当する場合)、次の画像タイプパターンマッチングアルゴリズムを利用する:

  1. 以下の表の各行rowについて、次の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムinputrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの 画像MIMEタイプ 備考
    00 00 01 00 FF FF FF FF なし。 image/x-icon Windowsアイコンシグネチャ。
    00 00 02 00 FF FF FF FF なし。 image/x-icon Windowsカーソルシグネチャ。
    42 4D FF FF なし。 image/bmp 文字列"BM"、BMPシグネチャ。
    47 49 46 38 37 61 FF FF FF FF FF FF なし。 image/gif 文字列"GIF87a"、GIFシグネチャ。
    47 49 46 38 39 61 FF FF FF FF FF FF なし。 image/gif 文字列"GIF89a"、GIFシグネチャ。
    52 49 46 46 00 00 00 00 57 45 42 50 56 50 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF なし。 image/webp 文字列"RIFF"の後に4つのバイト、続いて文字列"WEBPVP"。
    89 50 4E 47 0D 0A 1A 0A FF FF FF FF FF FF FF FF なし。 image/png エラーチェック用バイト、続いて文字列"PNG"、CR LF SUB LF、PNGシグネチャ。
    FF D8 FF FF FF FF なし。 image/jpeg JPEG開始マーカーの後に他のマーカーの指示バイト
  2. undefinedを返す。

6.2. 音声/動画タイプパターンの照合

どの音声または動画MIMEタイプバイトパターンバイト列 inputが一致するか(該当する場合)、次の音声または動画タイプパターンマッチングアルゴリズムを利用する:

  1. 以下の表の各行rowについて、次の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムinputrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの 音声または動画MIMEタイプ 備考
    46 4F 52 4D 00 00 00 00 41 49 46 46 FF FF FF FF 00 00 00 00 FF FF FF FF なし。 audio/aiff 文字列"FORM"の後に4つのバイト、続いて文字列"AIFF"、AIFFシグネチャ。
    49 44 33 FF FF FF なし。 audio/mpeg 文字列"ID3"、ID3v2付きMP3シグネチャ。
    4F 67 67 53 00 FF FF FF FF FF なし。 application/ogg 文字列"OggS"の後にNUL、Oggコンテナシグネチャ。
    4D 54 68 64 00 00 00 06 FF FF FF FF FF FF FF FF なし。 audio/midi 文字列"MThd"の後に32bitで6を表す4つのバイト、MIDIシグネチャ。
    52 49 46 46 00 00 00 00 41 56 49 20 FF FF FF FF 00 00 00 00 FF FF FF FF なし。 video/avi 文字列"RIFF"の後に4つのバイト、続いて文字列"AVI "、AVIシグネチャ。
    52 49 46 46 00 00 00 00 57 41 56 45 FF FF FF FF 00 00 00 00 FF FF FF FF なし。 audio/wave 文字列"RIFF"の後に4つのバイト、続いて文字列"WAVE"、WAVEシグネチャ。
  2. inputMP4のシグネチャに一致する場合、"video/mp4"を返す。

  3. inputWebMのシグネチャに一致する場合、"video/webm"を返す。

  4. inputID3なしMP3のシグネチャに一致する場合、"audio/mpeg"を返す。

  5. undefinedを返す。

6.2.1. MP4のシグネチャ

バイト列MP4のシグネチャと一致するかどうか判定するには、以下の手順を使用する:

  1. sequenceを照合対象とするバイト列とし、sequence[s]がsequences番目のバイトsequence[0]が最初のバイトであるとする。
  2. lengthsequence中のバイト数とする。
  3. lengthが12未満ならfalseを返す。
  4. box-sizesequence[0]~[3]の4バイトを、32ビット符号なしビッグエンディアン整数として解釈した値とする。
  5. lengthbox-size未満、またはbox-sizeを4で割った余りが0でない場合、falseを返す。
  6. sequence[4]~[7]の4バイトが0x66 0x74 0x79 0x70("ftyp")と等しくない場合、falseを返す。
  7. sequence[8]~[10]の3バイトが0x6D 0x70 0x34("mp4")と等しい場合、trueを返す。
  8. bytes-readを16とする。

    これは"major brand"のバージョン番号に対応する4バイトを無視している。

  9. bytes-readbox-size未満の間、以下を繰り返す:
    1. sequence[bytes-read]~[bytes-read+2]の3バイトが0x6D 0x70 0x34("mp4")と等しい場合、trueを返す。
    2. bytes-readを4増やす。
  10. falseを返す。

6.2.2. WebMのシグネチャ

バイト列WebMのシグネチャと一致するかどうか判定するには、以下の手順を使用する:

  1. sequenceを照合対象とするバイト列とし、sequence[s]がsequences番目のバイトsequence[0]が最初のバイトであるとする。
  2. lengthsequence中のバイト数とする。
  3. lengthが4未満ならfalseを返す。
  4. sequence[0]~[3]の4バイトが0x1A 0x45 0xDF 0xA3と等しくない場合、falseを返す。
  5. iterを4とする。
  6. iterlength未満かつiterが38未満の間、以下を繰り返す:
    1. sequence[iter]~[iter+1]の2バイトが0x42 0x82と等しい場合、
      1. iterを2増やす。
      2. iterlength以上なら、これらの手順を中止する。
      3. number sizesequence[iter]からvintパースした結果とする。
      4. iternumber sizeだけ増やす。
      5. iterlength-4以上なら、これらの手順を中止する。
      6. matchedパディング付きシーケンス照合0x77 0x65 0x62 0x6D("webm")をsequenceiterオフセットで実行した結果とする。
      7. matchedがtrueなら、これらの手順を中止しtrueを返す。
    2. iterを1増やす。
  7. falseを返す。

vintのパースは、バイト列sequence(サイズlength)のiterから開始して以下の手順を実行する:

  1. maskを128とする。
  2. max vint lengthを8とする。
  3. number sizeを1とする。
  4. indexを0とする。
  5. number sizemax vint length未満かつlength未満の間、以下を繰り返す:
    1. sequence[index] & maskが0でなければ、これらの手順を中止する。
    2. maskmask >> 1の値とする。
    3. number sizeを1増やす。
  6. parsed numbersequence[index] & ~maskとする。
  7. indexを1増やす。
  8. bytes remainingnumber size - 1とする。
  9. bytes remainingが0でない間、以下を繰り返す:
    1. parsed numberparsed number << 8とする。
    2. parsed numberparsed number | sequence[index]とする。
    3. indexを1増やす。
    4. indexlength以上ならこれらの手順を中止する。
    5. bytes remainingを1減らす。
  10. parsed numbernumber sizeを返す。

パディング付きシーケンス照合は、patternsequenceoffsetからendまでの範囲で、長さがendを超え、範囲[offset, end]でpatternのバイトが同順で含まれていて、先頭に0x00値のバイトが任意個並んでいる場合true、そうでなければfalseを返すことを意味する。

6.2.3. ID3なしMP3のシグネチャ

バイト列ID3なしMP3のシグネチャと一致するかどうか判定するには、以下の手順を使用する:

  1. sequenceを照合対象のバイト列とし、sequence[s]はsequenceバイト ssequence[0]はsequenceの最初のバイトとする。
  2. lengthsequenceバイト数とする。
  3. sを0で初期化する。
  4. mp3ヘッダー照合の結果がfalseなら、falseを返す。
  5. sequenceのオフセットsmp3フレーム解析を行う。
  6. mp3フレームサイズ算出の実行結果をskipped-bytesとする。
  7. skipped-bytesが4未満、またはskipped-bytess - lengthより大きい場合、falseを返す。
  8. sにskipped-bytesを加算する。
  9. mp3ヘッダー照合の結果がfalseならfalseを返し、そうでなければtrueを返す。

mp3ヘッダー照合は、バイト列sequence(長さlength)のオフセットsで以下の手順を実行する:

  1. lengthが4未満ならfalseを返す。
  2. sequence[s]が0xffでない、またはsequence[s + 1] & 0xe0が0xe0でない場合、falseを返す。
  3. layersequence[s + 1] & 0x06 >> 1の結果とする。
  4. layerが0ならfalseを返す。
  5. bit-ratesequence[s + 2] & 0xf0 >> 4の結果とする。
  6. bit-rateが15ならfalseを返す。
  7. sample-ratesequence[s + 2] & 0x0c >> 2の結果とする。
  8. sample-rateが3ならfalseを返す。
  9. freqsample-rateテーブルからsample-rateに対応する値とする。
  10. final-layerを4−(sequence[s + 1])の結果とする。
  11. final-layer & 0x06 >> 1が3でなければfalseを返す。
  12. trueを返す。

mp3フレームサイズ計算は以下の手順:

  1. versionが1ならscaleを72、それ以外は144とする。
  2. sizebitrate * scale / freqとする。
  3. padが0でなければsizeを1加算する。
  4. sizeを返す。

mp3フレーム解析は以下の手順:

  1. versionsequence[s + 1] & 0x18 >> 3とする。
  2. bitrate-indexをsequence[s + 2] & 0xf0 >> 4とする。
  3. version & 0x01が非ゼロなら、bitrateをmp2.5-ratesテーブルのbitrate-index番目の値とする。
  4. version & 0x01がゼロなら、bitrateをmp3-ratesテーブルのbitrate-index番目の値とする。
  5. samplerate-indexsequence[s + 2] & 0x0c >> 2とする。
  6. sampleratesample-rateテーブルからsamplerate-indexに対応する値とする。
  7. padsequence[s + 2] & 0x02 >> 1とする。
mp3-ratesテーブル
index mp3-rates
0 0
1 32000
2 40000
3 48000
4 56000
5 64000
6 80000
7 96000
8 112000
9 128000
10 160000
11 192000
12 224000
13 256000
14 320000
mp2.5-ratesテーブル
index mp2.5-rates
0 0
1 8000
2 16000
3 24000
4 32000
5 40000
6 48000
7 56000
8 64000
9 80000
10 96000
11 112000
12 128000
13 144000
14 160000
sample-rateテーブル
index samplerate
0 44100
1 48000
2 32000

6.3. フォントタイプパターンの照合

どのフォントMIMEタイプバイトパターンバイト列inputが一致するか(該当する場合)、次のフォントタイプパターンマッチングアルゴリズムを利用する:

  1. 以下の表の各行rowについて、次の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムinputrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの フォントMIMEタイプ 備考
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4C 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF なし。 application/vnd.ms-fontobject 34バイトの後に文字列"LP"、Embedded OpenTypeシグネチャ。
    00 01 00 00 FF FF FF FF なし。 font/ttf 4バイトでバージョン番号1.0を表す、TrueTypeシグネチャ。
    4F 54 54 4F FF FF FF FF なし。 font/otf 文字列"OTTO"、OpenTypeシグネチャ。
    74 74 63 66 FF FF FF FF なし。 font/collection 文字列"ttcf"、TrueType Collectionシグネチャ。
    77 4F 46 46 FF FF FF FF なし。 font/woff 文字列"wOFF"、Web Open Font Format 1.0シグネチャ。
    77 4F 46 32 FF FF FF FF なし。 font/woff2 文字列"wOF2"、Web Open Font Format 2.0シグネチャ。
  2. undefinedを返す。

6.4. アーカイブタイプパターンの照合

どのアーカイブMIMEタイプバイトパターンバイト列inputが一致するか(該当する場合)、次のアーカイブタイプパターンマッチングアルゴリズムを利用する:

  1. 以下の表の各行rowについて、次の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムinputrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの アーカイブMIMEタイプ 備考
    1F 8B 08 FF FF FF なし。 application/x-gzip GZIPアーカイブシグネチャ。
    50 4B 03 04 FF FF FF FF なし。 application/zip 文字列"PK"の後にETX EOT、ZIPアーカイブシグネチャ。
    52 61 72 21 1A 07 00 FF FF FF FF FF FF FF なし。 application/x-rar-compressed 文字列"Rar!"の後にSUB BEL NUL、RAR 4.xアーカイブシグネチャ。
  2. undefinedを返す。

7. リソースの計算されたMIMEタイプの決定

リソース算出MIMEタイプを決定するために、ユーザーエージェントは次のMIMEタイプスニッフィングアルゴリズムを用いなければならない:

  1. 指定MIMEタイプXML MIMEタイプまたはHTML MIMEタイプの場合、算出MIMEタイプ指定MIMEタイプとする。

    これ以降の手順を中止する。

  2. 指定MIMEタイプが未定義、または指定MIMEタイプエッセンスが"unknown/unknown"、"application/unknown"、または"*/*"の場合、sniff-scriptableフラグno-sniffフラグの逆にして不明なMIMEタイプ識別の規則を実行し、これ以降の手順を中止する。
  3. no-sniffフラグが設定されている場合、算出MIMEタイプ指定MIMEタイプとする。

    これ以降の手順を中止する。

  4. Apacheバグ確認フラグが設定されている場合、リソースがテキストかバイナリか判別する規則を実行し、これ以降の手順を中止する。
  5. 指定MIMEタイプがユーザーエージェントでサポートされている画像MIMEタイプの場合、matched-type画像タイプパターンマッチングアルゴリズムリソースヘッダーバイト列として与えた結果とする。
  6. matched-typeがundefinedでない場合、算出MIMEタイプmatched-typeとする。

    これ以降の手順を中止する。

  7. 指定MIMEタイプがユーザーエージェントでサポートされている音声または動画MIMEタイプの場合、matched-type音声または動画タイプパターンマッチングアルゴリズムリソースヘッダーバイト列として与えた結果とする。
  8. matched-typeがundefinedでない場合、算出MIMEタイプmatched-typeとする。

    これ以降の手順を中止する。

  9. 算出MIMEタイプ指定MIMEタイプとする。

7.1. 未知MIMEタイプのリソースの識別

sniff-scriptableフラグは、不明なMIMEタイプ識別の規則において、スクリプト可能MIMEタイプをスニッフィングするかどうか決定するために使用される。

不明なMIMEタイプ識別の規則を呼び出す際にsniff-scriptableフラグの設定が指定されていない場合、sniff-scriptableフラグは既定で未設定としなければならない。

不明なMIMEタイプを持つリソースresource算出MIMEタイプを決定するには、次の不明なMIMEタイプ識別の規則を実行する:

  1. sniff-scriptableフラグが設定されている場合、次の表の各行rowについて以下の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムresourceリソースヘッダーrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの 算出MIMEタイプ 備考
    3C 21 44 4F 43 54 59 50 45 20 48 54 4D 4C TT FF FF DF DF DF DF DF DF DF FF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<!DOCTYPE HTML"の後にタグ終了バイト
    3C 48 54 4D 4C TT FF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<HTML"の後にタグ終了バイト
    3C 48 45 41 44 TT FF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<HEAD"の後にタグ終了バイト
    3C 53 43 52 49 50 54 TT FF DF DF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<SCRIPT"の後にタグ終了バイト
    3C 49 46 52 41 4D 45 TT FF DF DF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<IFRAME"の後にタグ終了バイト
    3C 48 31 TT FF DF FF FF 空白バイト text/html 大文字小文字を区別しない文字列"<H1"の後にタグ終了バイト
    3C 44 49 56 TT FF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<DIV"の後にタグ終了バイト
    3C 46 4F 4E 54 TT FF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<FONT"の後にタグ終了バイト
    3C 54 41 42 4C 45 TT FF DF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<TABLE"の後にタグ終了バイト
    3C 41 TT FF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<A"の後にタグ終了バイト
    3C 53 54 59 4C 45 TT FF DF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<STYLE"の後にタグ終了バイト
    3C 54 49 54 4C 45 TT FF DF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<TITLE"の後にタグ終了バイト
    3C 42 TT FF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<B"の後にタグ終了バイト
    3C 42 4F 44 59 TT FF DF DF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<BODY"の後にタグ終了バイト
    3C 42 52 TT FF DF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<BR"の後にタグ終了バイト
    3C 50 TT FF DF FF 空白バイト text/html 大文字小文字を区別しない文字列"<P"の後にタグ終了バイト
    3C 21 2D 2D TT FF FF FF FF FF 空白バイト text/html 文字列"<!--"の後にタグ終了バイト
    3C 3F 78 6D 6C FF FF FF FF FF 空白バイト text/xml 文字列"<?xml"。
    25 50 44 46 2D FF FF FF FF FF なし。 application/pdf 文字列"%PDF-"、PDFシグネチャ。
  2. 次の表の各行rowについて、以下の手順を実行する:

    1. patternMatchedを、パターンマッチングアルゴリズムresourceリソースヘッダーrowの第1列・第2列・第3列の値を与えた結果とする。

    2. patternMatchedがtrueなら、rowの第4列の値を返す。

    バイトパターン パターンマスク 先頭のバイトで無視するもの 算出MIMEタイプ 備考
    25 21 50 53 2D 41 64 6F 62 65 2D FF FF FF FF FF FF FF FF FF FF FF なし。 application/postscript 文字列"%!PS-Adobe-"、PostScriptシグネチャ。
    FE FF 00 00 FF FF 00 00 なし。 text/plain UTF-16BE BOM
    FF FE 00 00 FF FF 00 00 なし。 text/plain UTF-16LE BOM
    EF BB BF 00 FF FF FF 00 なし。 text/plain UTF-8 BOM

    ユーザーエージェントは、追加のMIMEタイプをサポートするために、この表を暗黙的に拡張してもよい。

    ただし、ユーザーエージェントは、この表にすでに存在する算出MIMEタイプについて追加のバイトパターンを暗黙的に追加すべきではない。そうすると権限昇格の脆弱性を招くおそれがあるためである。

    ユーザーエージェントは、この表を拡張する際に権限昇格の脆弱性を導入してはならない。

  3. matchedTypeを、画像タイプパターンマッチングアルゴリズムresourceリソースヘッダーを与えて実行した結果とする。

  4. matchedTypeがundefinedでない場合、matchedTypeを返す。

  5. matchedTypeを、音声または動画タイプパターンマッチングアルゴリズムresourceリソースヘッダーを与えて実行した結果とする。

  6. matchedTypeがundefinedでない場合、matchedTypeを返す。

  7. matchedTypeを、アーカイブタイプパターンマッチングアルゴリズムresourceリソースヘッダーを与えて実行した結果とする。

  8. matchedTypeがundefinedでない場合、matchedTypeを返す。

  9. resourceリソースヘッダーバイナリデータバイトが含まれていない場合、"text/plain"を返す。

  10. "application/octet-stream"を返す。

7.2. 誤ラベルされたバイナリリソースのスニッフィング

バイナリリソースがプレーンテキストとして誤ってラベル付けされているかどうかを判定するには、次のリソースがテキストかバイナリか判別する規則を実行する:

  1. lengthバイト数としてリソースヘッダーの長さとする。
  2. lengthが2以上かつリソースヘッダーの最初の2バイトが0xFE 0xFF(UTF-16BE BOM)または0xFF 0xFE(UTF-16LE BOM)に等しい場合、算出MIMEタイプは"text/plain"とする。

    これ以降の手順を中止する。

  3. lengthが3以上かつリソースヘッダーの最初の3バイトが0xEF 0xBB 0xBF(UTF-8 BOM)に等しい場合、算出MIMEタイプは"text/plain"とする。

    これ以降の手順を中止する。

  4. リソースヘッダーバイナリデータバイトが含まれていない場合、算出MIMEタイプは"text/plain"とする。

    これ以降の手順を中止する。

  5. 算出MIMEタイプは"application/octet-stream"とする。

    リソースがテキストかバイナリか判別する規則算出MIMEタイプとしてスクリプト可能MIMEタイプを決定してはならない。これは権限昇格攻撃を許すおそれがあるためである。

8. コンテキスト固有のスニッフィング

コンテキストとは……。

特定のコンテキストでは、特定のサブセットのMIMEタイプに属するリソースのみを識別することが有用な場合がある。

そのようなコンテキストでは、リソース算出MIMEタイプを決定する際に、MIMEタイプスニッフィングアルゴリズムの代わりにコンテキスト固有スニッフィングアルゴリズムを用いるのが適切である。

コンテキスト固有スニッフィングアルゴリズムは、特定のコンテキストに関連するMIMEタイプであるリソースの場合のみ、そのリソース算出MIMEタイプを決定する。

8.1. ブラウジングコンテキストでのスニッフィング

MIMEタイプスニッフィングアルゴリズムを使用する。

8.2. 画像コンテキストでのスニッフィング

画像MIMEタイプリソースについて計算されたMIMEタイプを決定するには、以下の画像専用スニッフィング規則を実行する:

  1. 提供MIMEタイプXML MIMEタイプの場合、計算されたMIMEタイプ提供MIMEタイプとする。

    これらの手順を中止する。

  2. image-type-matched画像タイプパターン照合アルゴリズムリソースヘッダー(照合するバイト列)で実行した結果とする。
  3. image-type-matchedがundefinedでない場合、計算されたMIMEタイプimage-type-matchedとする。

    これらの手順を中止する。

  4. 計算されたMIMEタイプ提供MIMEタイプとする。

8.3. 音声/動画コンテキストでのスニッフィング

音声または動画MIMEタイプリソースについて計算されたMIMEタイプを決定するには、以下の音声・動画専用スニッフィング規則を実行する:

  1. 提供MIMEタイプXML MIMEタイプの場合、計算されたMIMEタイプ提供MIMEタイプとする。

    これらの手順を中止する。

  2. audio-or-video-type-matched音声/動画タイプパターン照合アルゴリズムリソースヘッダー(照合するバイト列)で実行した結果とする。
  3. audio-or-video-type-matchedがundefinedでない場合、計算されたMIMEタイプaudio-or-video-type-matchedとする。

    これらの手順を中止する。

  4. 計算されたMIMEタイプ提供MIMEタイプとする。

8.4. プラグインコンテキストでのスニッフィング

プラグインコンテキストでリソースフェッチされた場合、計算されたMIMEタイプを決定するには、以下のプラグインコンテキスト専用スニッフィング規則を実行する:

  1. 提供MIMEタイプが未定義の場合、計算されたMIMEタイプは"application/octet-stream"とする。
  2. 計算されたMIMEタイプ提供MIMEタイプとする。

8.5. スタイルコンテキストでのスニッフィング

スタイルコンテキストでリソースフェッチされた場合、その算出MIMEタイプを決定するには、次のスタイルコンテキストにおけるスニッフィング規則を実行する:

  1. 指定MIMEタイプが未定義の場合、…。
  2. 算出MIMEタイプ指定MIMEタイプとする。

8.6. スクリプトコンテキストでのスニッフィング

スクリプトコンテキストでリソースフェッチされた場合、計算されたMIMEタイプを決定するには、以下のスクリプトコンテキスト専用スニッフィング規則を実行する:

  1. 提供MIMEタイプが未定義の場合、 ….
  2. 計算されたMIMEタイプ提供MIMEタイプとする。

8.7. フォントコンテキストでのスニッフィング

フォントMIMEタイプリソースについて計算されたMIMEタイプを決定するには、以下のフォント専用スニッフィング規則を実行する:

  1. 提供MIMEタイプXML MIMEタイプの場合、計算されたMIMEタイプ提供MIMEタイプとする。

    これらの手順を中止する。

  2. font-type-matchedフォントタイプパターン照合アルゴリズムリソースヘッダー(照合するバイト列)で実行した結果とする。
  3. font-type-matchedがundefinedでない場合、計算されたMIMEタイプfont-type-matchedとする。

    これらの手順を中止する。

  4. 計算されたMIMEタイプ提供MIMEタイプとする。

8.8. テキストトラックコンテキストでのスニッフィング

計算されたMIMEタイプは"text/vtt"。

8.9. キャッシュマニフェストコンテキストでのスニッフィング

計算されたMIMEタイプは"text/cache-manifest"。

謝辞

この文書の過去の版を管理したAdam Barth氏とIan Hickson氏に特別な感謝を。

また、以下の方々にも感謝します: Alfred Hönes、 Andreu Botella、 Anne van Kesteren、 Ben Eidson、 Boris Zbarsky、 Darien Maillet Valentine、 David Singer、 Domenic Denicola、 Henri Sivonen、 Jean-Yves Avenard、 Jonathan Neal、 Joshua Cranmer、 Larry Masinter、 罗泽轩、 Mariko Kosaka、 Mark Pilgrim、 Paul Adenot、 Peter Occil、 Rob Buis、 Russ Cox、 Simon Pieters、 triple-underscore ― 彼らの多大な貢献に感謝いたします。

この現行標準はGordon P. Hemsley (me@gphemsley.org)によって執筆されています。

知的財産権

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)。本作業はクリエイティブ・コモンズ 表示 4.0 国際ライセンスの下でライセンスされています。一部がソースコードに組み込まれている場合、その部分はBSD 3-Clause Licenseの下でライセンスされます。

これは現行標準です。 特許審査版に興味のある方は 現行標準レビュー草案をご覧ください。

索引

本仕様で定義される用語

参照先で定義される用語

参考文献

規定参考文献

[ENCODING]
Anne van Kesteren. Encoding Standard. 現行標準. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch Standard. 現行標準. URL: https://fetch.spec.whatwg.org/
[HTTP-SEMANTICS]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP Semantics. 2022年6月. インターネット標準. URL: https://httpwg.org/specs/rfc9110.html
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. 現行標準. URL: https://infra.spec.whatwg.org/
[KEYWORDS]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997年3月. 最良現行慣行. URL: https://datatracker.ietf.org/doc/html/rfc2119
[MIMETYPE]
N. Freed; N. Borenstein. Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types. 1996年11月. 草案標準. URL: https://www.rfc-editor.org/rfc/rfc2046

参考情報

[FTP]
J. Postel; J. Reynolds. File Transfer Protocol. 1985年10月. インターネット標準. URL: https://www.rfc-editor.org/rfc/rfc959
[HTML]
Anne van Kesteren; et al. HTML Standard. 現行標準. URL: https://html.spec.whatwg.org/multipage/
[MEDIAQUERIES]
Florian Rivoal; Tab Atkins Jr.. Media Queries Level 4. URL: https://drafts.csswg.org/mediaqueries-4/
[RFC7303]
H. Thompson; C. Lilley. XML Media Types. 2014年7月. 提案標準. URL: https://www.rfc-editor.org/rfc/rfc7303
[RFC8081]
C. Lilley. The "font" Top-Level Media Type. 2017年2月. 提案標準. URL: https://www.rfc-editor.org/rfc/rfc8081
[SECCONTSNIFF]
Adam Barth; Juan Caballero; Dawn Song. Secure Content Sniffing for Web Browsers, or How to Stop Papers from Reviewing Themselves. 2009年5月. URL: https://www.adambarth.com/papers/2009/barth-caballero-song.pdf