要約

  • RFC 2231の継続番号はゼロから始まり、欠番なく一つずつ増える。文字集合と言語は最初の符号化部分で一度だけ宣言され、受信側は出現順ではなく番号順に完全な値を組み立ててから復号する。
  • 正しく復元されたfilenameも保存名の提案にすぎない。RFC 2183は、経路の除去、上書き防止、危険な保存先の回避、利用者の明示操作なしの実行禁止を受信側に求めている。

三つの欄に隠れた一つの名前

次のような説明用のヘッダーを考える。

filename*0*=utf-8'en'Quarterly%20; filename*1*=review%20; filename*2=final.pdf

これは三つの候補名ではない。先頭部分がUTF-8と言語情報を示し、二番目がパーセント符号化された続きを運び、三番目が符号化されていない末尾を運ぶ。連続した0、1、2がすべてそろって初めて、論理上の値Quarterly review final.pdfを取り出せる。

ここで、ヘッダーに並んだ順番を信用してはいけない。MIMEではパラメーターの順序そのものに意味がないため、*2が*0より先に現れても不思議ではない。受信実装は共通の基底名を認識し、ゼロ始まり、欠番なし、先頭ゼロなし、重複による曖昧さなしという条件を確かめ、添字の順でつなぐ必要がある。

各部分を別々の文字列として復号してから結合するのも危険である。文字集合と言語の宣言は最初にだけ置かれる。継続境界は転送上の都合であり、文字境界ではない。UTF-8の一文字を構成するオクテットが二つの部分に分かれれば、断片ごとの復号は置換文字を作ったり、別のパーサーと違う結果を生んだりする。

したがって実装上の順序は明確だ。パラメーター名を解析し、継続列の完全性を検証し、番号順に生のペイロードを結合し、符号化部分をオクテットへ戻し、宣言された文字集合で一度解釈する。その後で初めて、結果をContent-Dispositionのポリシーへ渡す。RFC 2231自身のSecurity Considerationsは短いが、文法と一回だけの文字集合宣言から、この境界は読み取れる。

復号の成功は保存の許可ではない

RFC 2231は表現方法を拡張した。オペレーティングシステムへの命令を新設したわけではない。権限の限界は、更新対象となったRFC 2183のContent-Dispositionで既に示されていた。

RFC 2183におけるfilenameは、本文部分をファイルとして取り出す際の推奨名である。受信するメールユーザーエージェントはそれを盲目的に使ってはならない。ディレクトリ情報を無視し、最後の構成要素だけを候補にする。既存ファイルの上書き、システム領域や起動領域への配置、特殊ファイルやパイプ、検索パス上の実行可能ファイルを警戒しなければならない。保存しただけで、利用者の明示操作なしに実行される状態も許されない。

完全に復元されたUTF-8の名前にも、../、絶対パス、制御文字、双方向表示制御、予約名、見せかけの拡張子は入り得る。パーセント復号は無害化ではない。文字集合の妥当性は送信者の本人確認ではない。filenameとContent-Typeが一致しても、中身の安全や実行許可は証明されない。

役割を分ける必要がある。MIMEパーサーは継続構造を判定する。デコーダーはオクテットをテキストにする。ファイル名ポリシーはローカルで安全な候補を生成する。保存層は許可された場所と衝突処理を決める。そして利用者または別の認可ポリシーが開くか実行するかを決める。一つの成功を次の許可証として使ってはならない。

著者欄にも勝手な連結をしない

RFC 2231の著者はNed FreedとKeith Mooreである。前身のRFC 2184も同じ二人を著者としている。この仕組みに関する共同著者の境界は明瞭だ。

Patrik Fältströmはインターネット国際化の重要人物だが、RFC 2231やRFC 2184の著者ではない。初期IDNA仕様のRFC 3490は、Fältström、Paul Hoffman、Adam Costelloの名を掲げる。隣接分野を一つの著者関係へまとめてしまうと、規格が守っている来歴を壊す。問題意識が近くても、文書、著者、合意範囲は別である。

Freedの広いMIMEへの貢献はIETF Datatrackerで確認できる。Nathaniel Borensteinは追悼文で、豊かなメールを求める自身の関心と、堅牢性・相互運用性を重視するFreedの関心が出会った経緯を述べた。RFC 2045はMIME本文形式、RFC 2047はメッセージヘッダー中の非ASCIIテキストを扱い、RFC 2231は残っていたパラメーター値の問題へ対象を絞った。

その限定は設計上の強さである。星印が付けばどのプロトコルでも自動的に同じ意味になるわけではない。採用する仕様が明示的に意味を与える必要がある。そして国際化された名前を運べることと、その名前が誰の主張かを認証することは別だ。

HTTPは符号化を継ぎ、継続を捨てた

RFC 8187はHTTPのパラメーター向けに関連する符号化形式を定め、UTF-8を必須にした一方、RFC 2231の継続方式を採用しなかった。HTTPには必要がなかったからである。系譜はつながっているが、契約は小さく作り直された。

HTTPのContent-Dispositionを定めるRFC 6266も、ファイル名を助言的な情報と位置づける。経路成分を捨て、保存先を受信側が制御し、危険な拡張子や制御文字、特殊名を処理する。サーバーがラベルを提案しても、クライアントのファイルシステムを支配する権限は得られない。

RFC 2231の教訓は二重である。相互運用には、ゼロ始まりの連続番号、先頭での一度きりの宣言、決まった復元・復号順序という厳密さが要る。同時に安全性には、その厳密さが証明しないものを区別する厳密さが要る。文字列は復元できる。それでも信用は別の層で獲得しなければならない。

出典