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の本質は、 mimeTypeのtype、U+002F(/)、mimeTypeのsubtypeの順で構成されます。
MIMEタイプは、ユーザーエージェントがサポートする場合、 ユーザーエージェントがそのリソースを解釈し、ユーザーに提示できる機能を持つことを意味します。
理想的には、より厳密に記述すべきです。w3c/preload #113
ユーザーエージェントがサポートするMIMEタイプを最小化するには、MIMEタイプmimeTypeを受け取り、以下の手順を実行します。返す値はASCII文字列です。
-
mimeTypeがJavaScript MIMEタイプなら、"
text/javascript
"を返す。 -
mimeTypeがJSON MIMEタイプなら、"
application/json
"を返す。 -
mimeTypeの本質が"
image/svg+xml
"なら、"image/svg+xml
"を返す。SVGは他のXML MIMEタイプと区別する価値があります。
-
mimeTypeがXML MIMEタイプなら、"
application/xml
"を返す。 -
mimeTypeがユーザーエージェントがサポートするなら、mimeTypeの本質を返す。
-
空文字列を返す。
このアルゴリズムの目的は、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を受け取り、以下の手順を実行する:
-
inputの先頭および末尾のHTTP 空白を削除する。
-
positionをinputの位置変数とし、最初はinputの先頭を指す。
-
typeを、positionを指定してinputからU+002F (/) ではないコードポイントの並びを収集した結果とする。
-
typeが空文字列であるか、HTTPトークンコードポイントのみで構成されていない場合、失敗を返す。
-
positionがinputの末尾を越えている場合、失敗を返す。
-
positionを1進める。(U+002F (/) を飛ばす。)
-
subtypeを、positionを指定してinputからU+003B (;) ではないコードポイントの並びを収集した結果とする。
-
subtypeの末尾からHTTP空白を削除する。
-
subtypeが空文字列であるか、HTTPトークンコードポイントのみで構成されていない場合、失敗を返す。
-
mimeTypeを新しいMIMEタイプレコードとし、typeはtypeをASCII小文字で、subtypeはsubtypeをASCII小文字とする。
-
positionがinputの末尾を越えていない間、以下を繰り返す:
-
positionを1進める。(U+003B (;) を飛ばす。)
-
positionを指定してinputからHTTP空白の並びを収集する。
これはASCII空白のスキップに概ね相当するが、HTTP空白を使用し、ASCII空白ではない。
-
positionを指定してinputからU+003B (;) または U+003D (=) ではないコードポイントの並びを収集し、parameterNameとする。
-
parameterNameをASCII小文字にする。
-
positionがinputの末尾を越えていない場合:
-
positionがinputの末尾を越えている場合、中断する。
-
parameterValueをnullとする。
-
positionのinput内のコードポイントがU+0022 (") ならば:
-
parameterValueに、positionとtrueを指定しinputからHTTP引用文字列を収集した結果を設定する。
-
positionを指定してinputからU+003B (;) ではないコードポイントの並びを収集する。
例:
text/html;charset="shift_jis"iso-2022-jp
の場合、text/html;charset=shift_jis
となる。
-
-
それ以外の場合:
-
すべて以下が真なら:
- parameterNameが空文字列でない
- parameterNameがHTTPトークンコードポイントのみで構成されている
- parameterValueがHTTP引用文字列トークンコードポイントのみで構成されている
- mimeTypeのparameters[parameterName]が存在しない
その場合、設定する mimeTypeの parameters[parameterName] を parameterValueに。
-
-
mimeTypeを返す。
バイト列からMIMEタイプを構文解析するには、バイト列inputを受け取り、 以下の手順を実行する:
-
stringをinputの等価デコードしたものとする。
-
stringでMIMEタイプを解析する結果を返す。
4.5. MIMEタイプの直列化
MIMEタイプを直列化するには、MIMEタイプ mimeTypeが与えられたとき、次の手順を実行する:
-
serializationをmimeTypeのtype、U+002F (/)、mimeTypeのsubtypeを連結したものとする。
-
各 name → value をmimeTypeのparametersから取り出し:
-
serializationにU+003B (;)を追加する。
-
serializationにnameを追加する。
-
serializationにU+003D (=)を追加する。
-
valueがHTTPトークンコードポイントのみで構成されていない、またはvalueが空文字列の場合:
-
value内のU+0022 (")またはU+005C (\)の各出現の前にU+005C (\)を付ける。
-
valueの先頭にU+0022 (")を付加する。
-
valueの末尾にU+0022 (")を付加する。
-
-
serializationにvalueを追加する。
-
-
serializationを返す。
MIMEタイプをバイト列に直列化するには、MIMEタイプ mimeTypeが与えられたとき、次の手順を実行する:
-
stringSerializationをmimeTypeでMIMEタイプを直列化する結果とする。
-
stringSerializationを等価エンコードしたものを返す。
4.6. MIMEタイプグループ
画像MIMEタイプは、MIMEタイプであり、そのtypeが"image
"であるもの。
音声または動画MIMEタイプは、MIMEタイプであり、typeが"audio
"または"video
"であるもの、またはessenceが"application/ogg
"であるもの。
フォントMIMEタイプは、MIMEタイプであり、typeが"font
"であるもの、またはessenceが下記いずれかであるもの:[RFC8081]
application/font-cff
application/font-otf
application/font-sfnt
application/font-ttf
application/font-woff
application/vnd.ms-fontobject
application/vnd.ms-opentype
ZIPベースMIMEタイプは、MIMEタイプであり、subtypeが"+zip
"で終わるもの、またはessenceが下記いずれかであるもの:
application/zip
アーカイブMIMEタイプは、MIMEタイプであり、essenceが下記いずれかであるもの:
application/x-rar-compressed
application/zip
application/x-gzip
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が下記いずれかであるもの:
application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/javascript1.0
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/javascript1.4
text/javascript1.5
text/jscript
text/livescript
text/x-ecmascript
text/x-javascript
文字列は、JavaScript MIMEタイプessence一致であり、ASCII大文字小文字無視でJavaScript MIMEタイプessence文字列のいずれかと一致する場合。
このフックは
type
属性や
script
要素で使用される。[HTML]
JSON MIMEタイプは、MIMEタイプであり、subtypeが"+json
"で終わるもの、またはessenceが"application/json
"または"text/json
"であるもの。
5. リソースの取り扱い
リソースとは ...。
ユーザーエージェントは、取り扱う各リソースについて、次の関連メタデータを管理しなければならない:
- 指定MIMEタイプ。MIMEタイプであり、指定MIMEタイプ検出アルゴリズムによって決定される。
- Apacheバグ確認フラグ。初期状態は未設定。
-
no-sniffフラグ。ユーザーエージェントがリソースに対してスニッフィングを行わない場合は設定され、それ以外は未設定。
ユーザーエージェントは、サイトとの過去の経験など外部情報を用いて、特定のリソースのスニッフィングを回避するかどうか判断できる。また、すべてのリソースに対してスニッフィングを回避することもできる。ただし、スニッフィングを回避しても、MIMEタイプスニッフィングアルゴリズムの使用義務は免除されない。
- 算出MIMEタイプ。MIMEタイプであり、MIMEタイプスニッフィングアルゴリズムによって決定される。
5.1. リソースメタデータの解釈
リソースの指定MIMEタイプは、そのリソースに関連する外部ソースからユーザーエージェントに提供される。 この情報の取得方法は、リソースの取得方法により異なる。
リソースの指定MIMEタイプを決定するには、ユーザーエージェントは以下の指定MIMEタイプ検出アルゴリズムを用いなければならない:
- supplied-typeをnullとする。
-
リソースがHTTP経由で取得された場合、以下を実行する:
-
一つ以上の
Content-Type
ヘッダーがリソースに関連付けられている場合、以下を実行する:-
supplied-typeに、リソースに関連付けられている最後の
Content-Type
ヘッダーの値を設定する。ファイル拡張子は、HTTP経由で取得されたリソースの指定MIMEタイプの決定には使用しない。これは信頼性が低く、容易に偽装可能であるためである。
-
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 31text/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 31text/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 38text/plain; charset=UTF-8
指定MIMEタイプ検出アルゴリズムは、これらの正確なバイト列を検出する。これは、古いApacheの一部インストールにバグがあり、認識できないMIMEタイプのファイルを提供する際にこれらのContent-Typeヘッダーを返すためである。
-
supplied-typeに、リソースに関連付けられている最後の
-
一つ以上の
- リソースがファイルシステムから直接取得された場合、supplied-typeにファイルシステムが提供したMIMEタイプを設定する。
- リソースが他のプロトコル(FTPなど)経由で取得された場合、supplied-typeにそのプロトコルで決定されたMIMEタイプを設定する(該当する場合)。
-
supplied-typeがMIMEタイプでない場合、指定MIMEタイプは未定義とする。
これらの手順を中止する。
- 指定MIMEタイプはsupplied-typeとする。
5.2. リソースヘッダーの読み取り
リソースヘッダーは、バイト列であり、リソースの先頭部分として、リソースヘッダーを読み取るによって定義される。
リソースヘッダーを読み取るには、次の手順を実行する:
- bufferをバイト列とする。
-
バイトをリソースからbufferに読み込む。次のいずれかの条件を満たすまで繰り返す:
bufferのバイト数が1445以上の場合、MIMEタイプスニッフィングアルゴリズムは大多数のケースで決定的となる。
ただし、回線が遅いなどの理由で、ユーザーエージェントが合理的な時間で1445バイトを読み取れない場合もある。
- リソースヘッダーはbufferとする。
リソースヘッダーは、各リソースごとに一度だけ決定すればよい。
6. MIMEタイプパターンの照合
バイトパターンは、バイト列であり、パターンマッチングアルゴリズムにおいて照合用テンプレートとして使われる。
パターンマスクは、バイト列であり、バイトがバイトパターンとの比較でどれだけ重要かを パターンマッチングアルゴリズムで決定するために使用する。
パターンマスクでは、0xFFはバイトが厳密に重要であること、0xDFはバイトがASCIIの大文字小文字無視で重要であること、0x00はバイトが重要でないことを示す。
特定のバイト列が所定のバイトパターンに一致するかどうかは、以下のパターンマッチングアルゴリズムで判定する。これは、バイト列 input、バイトパターン pattern、パターンマスク mask、無視する集合のバイト ignored を受け取り、trueまたはfalseを返す。
-
sを0とする。
-
s < inputの長さの間、繰り返す:
-
pを0とする。
-
p < patternの長さの間、繰り返す:
-
maskedDataをinput[s]とmask[p]にビットAND演算子を適用した結果とする。
-
maskedDataがpattern[p]と等しくない場合、falseを返す。
-
sをs + 1にする。
-
pをp + 1にする。
-
-
trueを返す。
6.1. 画像タイプパターンの照合
どの画像MIMEタイプのバイトパターンにバイト列inputが一致するか(該当する場合)、次の画像タイプパターンマッチングアルゴリズムを利用する:
-
以下の表の各行rowについて、次の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにinput、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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開始マーカーの後に他のマーカーの指示バイト。 -
-
undefinedを返す。
6.2. 音声/動画タイプパターンの照合
どの音声または動画MIMEタイプのバイトパターンにバイト列 inputが一致するか(該当する場合)、次の音声または動画タイプパターンマッチングアルゴリズムを利用する:
-
以下の表の各行rowについて、次の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにinput、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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シグネチャ。 -
-
inputがMP4のシグネチャに一致する場合、"
video/mp4
"を返す。 -
inputがWebMのシグネチャに一致する場合、"
video/webm
"を返す。 -
inputがID3なしMP3のシグネチャに一致する場合、"
audio/mpeg
"を返す。 -
undefinedを返す。
6.2.1. MP4のシグネチャ
バイト列MP4のシグネチャと一致するかどうか判定するには、以下の手順を使用する:
- sequenceを照合対象とするバイト列とし、sequence[s]がsequenceのs番目のバイト、sequence[0]が最初のバイトであるとする。
- lengthをsequence中のバイト数とする。
- lengthが12未満ならfalseを返す。
- box-sizeをsequence[0]~[3]の4バイトを、32ビット符号なしビッグエンディアン整数として解釈した値とする。
- lengthがbox-size未満、またはbox-sizeを4で割った余りが0でない場合、falseを返す。
-
sequence[4]~[7]の4バイトが0x66 0x74 0x79 0x70("
ftyp
")と等しくない場合、falseを返す。 -
sequence[8]~[10]の3バイトが0x6D 0x70 0x34("
mp4
")と等しい場合、trueを返す。 -
bytes-readを16とする。
これは"major brand"のバージョン番号に対応する4バイトを無視している。
-
bytes-readがbox-size未満の間、以下を繰り返す:
-
sequence[bytes-read]~[bytes-read+2]の3バイトが0x6D 0x70
0x34("
mp4
")と等しい場合、trueを返す。 - bytes-readを4増やす。
-
sequence[bytes-read]~[bytes-read+2]の3バイトが0x6D 0x70
0x34("
- falseを返す。
6.2.2. WebMのシグネチャ
バイト列WebMのシグネチャと一致するかどうか判定するには、以下の手順を使用する:
- sequenceを照合対象とするバイト列とし、sequence[s]がsequenceのs番目のバイト、sequence[0]が最初のバイトであるとする。
- lengthをsequence中のバイト数とする。
- lengthが4未満ならfalseを返す。
- sequence[0]~[3]の4バイトが0x1A 0x45 0xDF 0xA3と等しくない場合、falseを返す。
- iterを4とする。
-
iterがlength未満かつiterが38未満の間、以下を繰り返す:
-
sequence[iter]~[iter+1]の2バイトが0x42 0x82と等しい場合、
- iterを2増やす。
- iterがlength以上なら、これらの手順を中止する。
- number sizeをsequence[iter]から
vint
をパースした結果とする。 - iterをnumber sizeだけ増やす。
- iterがlength-4以上なら、これらの手順を中止する。
- matchedをパディング付きシーケンス照合0x77 0x65 0x62
0x6D("
webm
")をsequenceのiterオフセットで実行した結果とする。 - matchedがtrueなら、これらの手順を中止しtrueを返す。
- iterを1増やす。
-
sequence[iter]~[iter+1]の2バイトが0x42 0x82と等しい場合、
- falseを返す。
vint
のパースは、バイト列sequence(サイズlength)のiterから開始して以下の手順を実行する:
- maskを128とする。
- max vint lengthを8とする。
- number sizeを1とする。
- indexを0とする。
-
number sizeがmax vint length未満かつlength未満の間、以下を繰り返す:
- sequence[index] & maskが0でなければ、これらの手順を中止する。
- maskをmask >> 1の値とする。
- number sizeを1増やす。
- parsed numberをsequence[index] & ~maskとする。
- indexを1増やす。
- bytes remainingをnumber size - 1とする。
-
bytes remainingが0でない間、以下を繰り返す:
- parsed numberをparsed number << 8とする。
- parsed numberをparsed number | sequence[index]とする。
- indexを1増やす。
- indexがlength以上ならこれらの手順を中止する。
- bytes remainingを1減らす。
- parsed numberとnumber sizeを返す。
パディング付きシーケンス照合は、patternをsequenceのoffsetからendまでの範囲で、長さがendを超え、範囲[offset, end]でpatternのバイトが同順で含まれていて、先頭に0x00値のバイトが任意個並んでいる場合true、そうでなければfalseを返すことを意味する。
6.2.3. ID3なしMP3のシグネチャ
バイト列ID3なしMP3のシグネチャと一致するかどうか判定するには、以下の手順を使用する:
- sequenceを照合対象のバイト列とし、sequence[s]はsequenceのバイト s、sequence[0]はsequenceの最初のバイトとする。
- lengthをsequenceのバイト数とする。
- sを0で初期化する。
- mp3ヘッダー照合の結果がfalseなら、falseを返す。
- sequenceのオフセットsでmp3フレーム解析を行う。
- mp3フレームサイズ算出の実行結果をskipped-bytesとする。
- skipped-bytesが4未満、またはskipped-bytesがs - lengthより大きい場合、falseを返す。
- sにskipped-bytesを加算する。
- mp3ヘッダー照合の結果がfalseならfalseを返し、そうでなければtrueを返す。
mp3ヘッダー照合は、バイト列sequence(長さlength)のオフセットsで以下の手順を実行する:
- lengthが4未満ならfalseを返す。
- sequence[s]が0xffでない、またはsequence[s + 1] & 0xe0が0xe0でない場合、falseを返す。
- layerをsequence[s + 1] & 0x06 >> 1の結果とする。
- layerが0ならfalseを返す。
- bit-rateをsequence[s + 2] & 0xf0 >> 4の結果とする。
- bit-rateが15ならfalseを返す。
- sample-rateをsequence[s + 2] & 0x0c >> 2の結果とする。
- sample-rateが3ならfalseを返す。
- freqをsample-rateテーブルからsample-rateに対応する値とする。
- final-layerを4−(sequence[s + 1])の結果とする。
- final-layer & 0x06 >> 1が3でなければfalseを返す。
- trueを返す。
mp3フレームサイズ計算は以下の手順:
- versionが1ならscaleを72、それ以外は144とする。
- sizeをbitrate * scale / freqとする。
- padが0でなければsizeを1加算する。
- sizeを返す。
mp3フレーム解析は以下の手順:
- versionをsequence[s + 1] & 0x18 >> 3とする。
- bitrate-indexをsequence[s + 2] & 0xf0 >> 4とする。
- version & 0x01が非ゼロなら、bitrateをmp2.5-ratesテーブルのbitrate-index番目の値とする。
- version & 0x01がゼロなら、bitrateをmp3-ratesテーブルのbitrate-index番目の値とする。
- samplerate-indexをsequence[s + 2] & 0x0c >> 2とする。
- samplerateをsample-rateテーブルからsamplerate-indexに対応する値とする。
- padをsequence[s + 2] & 0x02 >> 1とする。
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 |
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 |
index | samplerate |
---|---|
0 | 44100 |
1 | 48000 |
2 | 32000 |
6.3. フォントタイプパターンの照合
どのフォントMIMEタイプのバイトパターンにバイト列inputが一致するか(該当する場合)、次のフォントタイプパターンマッチングアルゴリズムを利用する:
-
以下の表の各行rowについて、次の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにinput、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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シグネチャ。 -
-
undefinedを返す。
6.4. アーカイブタイプパターンの照合
どのアーカイブMIMEタイプのバイトパターンにバイト列inputが一致するか(該当する場合)、次のアーカイブタイプパターンマッチングアルゴリズムを利用する:
-
以下の表の各行rowについて、次の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにinput、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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アーカイブシグネチャ。 -
-
undefinedを返す。
7. リソースの計算されたMIMEタイプの決定
リソースの算出MIMEタイプを決定するために、ユーザーエージェントは次のMIMEタイプスニッフィングアルゴリズムを用いなければならない:
-
指定MIMEタイプがXML MIMEタイプまたはHTML MIMEタイプの場合、算出MIMEタイプは指定MIMEタイプとする。
これ以降の手順を中止する。
-
指定MIMEタイプが未定義、または指定MIMEタイプのエッセンスが"
unknown/unknown
"、"application/unknown
"、または"*/*
"の場合、sniff-scriptableフラグをno-sniffフラグの逆にして不明なMIMEタイプ識別の規則を実行し、これ以降の手順を中止する。 -
no-sniffフラグが設定されている場合、算出MIMEタイプは指定MIMEタイプとする。
これ以降の手順を中止する。
- Apacheバグ確認フラグが設定されている場合、リソースがテキストかバイナリか判別する規則を実行し、これ以降の手順を中止する。
- 指定MIMEタイプがユーザーエージェントでサポートされている画像MIMEタイプの場合、matched-typeを画像タイプパターンマッチングアルゴリズムにリソースヘッダーをバイト列として与えた結果とする。
-
matched-typeがundefinedでない場合、算出MIMEタイプはmatched-typeとする。
これ以降の手順を中止する。
- 指定MIMEタイプがユーザーエージェントでサポートされている音声または動画MIMEタイプの場合、matched-typeを音声または動画タイプパターンマッチングアルゴリズムにリソースヘッダーをバイト列として与えた結果とする。
-
matched-typeがundefinedでない場合、算出MIMEタイプはmatched-typeとする。
これ以降の手順を中止する。
- 算出MIMEタイプは指定MIMEタイプとする。
7.1. 未知MIMEタイプのリソースの識別
sniff-scriptableフラグは、不明なMIMEタイプ識別の規則において、スクリプト可能MIMEタイプをスニッフィングするかどうか決定するために使用される。
不明なMIMEタイプ識別の規則を呼び出す際にsniff-scriptableフラグの設定が指定されていない場合、sniff-scriptableフラグは既定で未設定としなければならない。
不明なMIMEタイプを持つリソースresourceの算出MIMEタイプを決定するには、次の不明なMIMEタイプ識別の規則を実行する:
-
sniff-scriptableフラグが設定されている場合、次の表の各行rowについて以下の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにresourceのリソースヘッダー、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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シグネチャ。 -
-
次の表の各行rowについて、以下の手順を実行する:
-
patternMatchedを、パターンマッチングアルゴリズムにresourceのリソースヘッダー、rowの第1列・第2列・第3列の値を与えた結果とする。
-
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タイプについて追加のバイトパターンを暗黙的に追加すべきではない。そうすると権限昇格の脆弱性を招くおそれがあるためである。
ユーザーエージェントは、この表を拡張する際に権限昇格の脆弱性を導入してはならない。
-
-
matchedTypeを、画像タイプパターンマッチングアルゴリズムにresourceのリソースヘッダーを与えて実行した結果とする。
-
matchedTypeがundefinedでない場合、matchedTypeを返す。
-
matchedTypeを、音声または動画タイプパターンマッチングアルゴリズムにresourceのリソースヘッダーを与えて実行した結果とする。
-
matchedTypeがundefinedでない場合、matchedTypeを返す。
-
matchedTypeを、アーカイブタイプパターンマッチングアルゴリズムにresourceのリソースヘッダーを与えて実行した結果とする。
-
matchedTypeがundefinedでない場合、matchedTypeを返す。
-
resourceのリソースヘッダーにバイナリデータバイトが含まれていない場合、"
text/plain
"を返す。 -
"
application/octet-stream
"を返す。
7.2. 誤ラベルされたバイナリリソースのスニッフィング
バイナリリソースがプレーンテキストとして誤ってラベル付けされているかどうかを判定するには、次のリソースがテキストかバイナリか判別する規則を実行する:
- lengthをバイト数としてリソースヘッダーの長さとする。
-
lengthが2以上かつリソースヘッダーの最初の2バイトが0xFE 0xFF(UTF-16BE BOM)または0xFF 0xFE(UTF-16LE
BOM)に等しい場合、算出MIMEタイプは"
text/plain
"とする。これ以降の手順を中止する。
-
lengthが3以上かつリソースヘッダーの最初の3バイトが0xEF 0xBB 0xBF(UTF-8 BOM)に等しい場合、算出MIMEタイプは"
text/plain
"とする。これ以降の手順を中止する。
-
リソースヘッダーにバイナリデータバイトが含まれていない場合、算出MIMEタイプは"
text/plain
"とする。これ以降の手順を中止する。
-
算出MIMEタイプは"
application/octet-stream
"とする。リソースがテキストかバイナリか判別する規則が算出MIMEタイプとしてスクリプト可能MIMEタイプを決定してはならない。これは権限昇格攻撃を許すおそれがあるためである。
8. コンテキスト固有のスニッフィング
コンテキストとは……。
特定のコンテキストでは、特定のサブセットのMIMEタイプに属するリソースのみを識別することが有用な場合がある。
そのようなコンテキストでは、リソースの算出MIMEタイプを決定する際に、MIMEタイプスニッフィングアルゴリズムの代わりにコンテキスト固有スニッフィングアルゴリズムを用いるのが適切である。
コンテキスト固有スニッフィングアルゴリズムは、特定のコンテキストに関連するMIMEタイプであるリソースの場合のみ、そのリソースの算出MIMEタイプを決定する。
8.1. ブラウジングコンテキストでのスニッフィング
MIMEタイプスニッフィングアルゴリズムを使用する。
8.2. 画像コンテキストでのスニッフィング
画像MIMEタイプのリソースについて計算されたMIMEタイプを決定するには、以下の画像専用スニッフィング規則を実行する:
-
提供MIMEタイプがXML MIMEタイプの場合、計算されたMIMEタイプは提供MIMEタイプとする。
これらの手順を中止する。
- image-type-matchedを画像タイプパターン照合アルゴリズムをリソースヘッダー(照合するバイト列)で実行した結果とする。
-
image-type-matchedがundefinedでない場合、計算されたMIMEタイプはimage-type-matchedとする。
これらの手順を中止する。
- 計算されたMIMEタイプは提供MIMEタイプとする。
8.3. 音声/動画コンテキストでのスニッフィング
音声または動画MIMEタイプのリソースについて計算されたMIMEタイプを決定するには、以下の音声・動画専用スニッフィング規則を実行する:
-
提供MIMEタイプがXML MIMEタイプの場合、計算されたMIMEタイプは提供MIMEタイプとする。
これらの手順を中止する。
- audio-or-video-type-matchedを音声/動画タイプパターン照合アルゴリズムをリソースヘッダー(照合するバイト列)で実行した結果とする。
-
audio-or-video-type-matchedがundefinedでない場合、計算されたMIMEタイプはaudio-or-video-type-matchedとする。
これらの手順を中止する。
- 計算されたMIMEタイプは提供MIMEタイプとする。
8.4. プラグインコンテキストでのスニッフィング
プラグインコンテキストでリソースがフェッチされた場合、計算されたMIMEタイプを決定するには、以下のプラグインコンテキスト専用スニッフィング規則を実行する:
-
提供MIMEタイプが未定義の場合、計算されたMIMEタイプは"
application/octet-stream
"とする。 - 計算されたMIMEタイプは提供MIMEタイプとする。
8.5. スタイルコンテキストでのスニッフィング
スタイルコンテキストでリソースがフェッチされた場合、その算出MIMEタイプを決定するには、次のスタイルコンテキストにおけるスニッフィング規則を実行する:
8.6. スクリプトコンテキストでのスニッフィング
スクリプトコンテキストでリソースがフェッチされた場合、計算されたMIMEタイプを決定するには、以下のスクリプトコンテキスト専用スニッフィング規則を実行する:
- 提供MIMEタイプが未定義の場合、 ….
- 計算されたMIMEタイプは提供MIMEタイプとする。
8.7. フォントコンテキストでのスニッフィング
フォントMIMEタイプのリソースについて計算されたMIMEタイプを決定するには、以下のフォント専用スニッフィング規則を実行する:
-
提供MIMEタイプがXML MIMEタイプの場合、計算されたMIMEタイプは提供MIMEタイプとする。
これらの手順を中止する。
- font-type-matchedをフォントタイプパターン照合アルゴリズムをリソースヘッダー(照合するバイト列)で実行した結果とする。
-
font-type-matchedがundefinedでない場合、計算されたMIMEタイプはfont-type-matchedとする。
これらの手順を中止する。
- 計算された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の下でライセンスされます。
これは現行標準です。 特許審査版に興味のある方は 現行標準レビュー草案をご覧ください。