はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、ブラウザが誤解釈しないよう、Web3 URLの返却データに適切なMIMEタイプを与える仕組みを提案しているERC6860の拡張仕様を提案しているERC7087についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。
概要
ERC7087は、ERC6860で定義されている web3:// プロトコルを拡張する提案です。
web3:// に対応していないスマートコントラクトを「auto モード」で呼び出したとき、返ってくるデータの種類(MIMEタイプ)が次のどちらかの状態になっています。
ERC6860については以下の記事を参考にしてください。
- スマートコントラクト側で明示されておらず、利用者から見ると暗黙的になっている
- 返却されるデータの中に、「RFC 2397 data URL(データそのものとその種別を一体で表現するURL形式)」として埋め込まれている
ここでいうMIMEタイプとは、「これはHTMLです」、「これは画像です」、「これはJSONです」といった、データの種類を表す識別子のことです。
例えば、 text/html や image/png のような文字列です。
この標準では、こうしたケースでも web3:// 経由でデータを取得するときに、追加のクエリパラメータを使ってMIMEタイプを得られるようにします。
さらに、スマートコントラクトがRFC 2397 data URLを返す場合、そのデータがdata URLであることをURL側で指定できるようにし、web3:// プロトコル側で中身をデコードした上で、data URL内で宣言されているMIMEタイプ情報を添えて返せるようにすることを目指しています。
動機
Webブラウザでデータを正しく表示するためには、「このレスポンスはどんな種類のデータか」を示す Content-Type ヘッダーが付いていることが強く推奨されます。
これが無い、あるいは不正確だと、ブラウザが内容を誤解釈し、文字化けやレイアウト崩れ、ダウンロード扱いになるなど、期待しない表示になる可能性があります。
web3:// プロトコルには「manual モード」と「auto モード」の2つのモードがあります。
それぞれの役割はおおまかに以下のようになっています。
| モード名 | 説明 |
|---|---|
manual モード |
スマートコントラクトが専用のインターフェースを実装し、「manual モードで動作したい」と明示的に指定するモードです。この場合、ERC6860で定義されている仕組みを使って、スマートコントラクト側が返却データの MIMEタイプを明示することが期待されています。 |
auto モード |
専用のインターフェースで「auto モード」と明示したスマートコントラクトだけでなく、何も指定していない「普通の」スマートコントラクトに対しても使われるモードです。明示的に auto モードを選んでいるコントラクトであればMIMEタイプを返してくれることも期待できますが、何も対応していない既存コントラクトについては、MIMEタイプがわからない前提になります。 |
問題は、この auto モード側です。
web3:// を意識して作られていない既存コントラクトは、ブラウザに返したいデータを持っていても、その種類をプロトコル側に正しく伝える手段がありません。
場合によっては、返却データの中にRFC 2397 data URL形式でMIMEタイプが含まれていることもありますが、プロトコルから見ると「ただのバイト列」であり、それをどう扱うかをURLやブラウザ側が判断しにくくなっています。
ERC6860は manual モードのスマートコントラクトについては、MIMEタイプをきちんと扱う仕組みを提供していますが、auto モードで既存コントラクトを扱うときには空白が残っていました。
この標準は、その空白を埋めることを目的としています。
具体的には、以下の2点を実現しようとしています。
-
web3://URL に追加のクエリパラメータを導入し、URL側で「このリクエストで期待するMIMEタイプ」を指定できるようにすること
これにより、スマートコントラクトがMIMEタイプを教えてくれない場合でも、web3://プロトコルは適切なContent-Typeを付けてブラウザに返せるようになります。 -
スマートコントラクトがRFC 2397 data URLを返す場合に、そのデータがdata URLであることをURLで明示できるようにすること
こうすることで、web3://プロトコルは data URL をいったんデコードし、中に含まれている「本来のデータ」と「そのMIMEタイプ」を取り出して、ブラウザにとって扱いやすい形で返せるようになります。
このように、ブラウザが期待どおりにコンテンツを解釈・表示できるようにするために、ERC6860を補完する形で、auto モードや既存コントラクトでもMIMEタイプをきちんと扱えるようにするのが、この標準の狙いです。
仕様
MIMEタイプを指定する3つのクエリパラメータ
MIMEタイプを決める方法として、以下の3つが用意されています。
| クエリパラメータ | 説明 |
|---|---|
mime.content=<contentType> |
<contentType> にRFC6838で定義されている正式なMIMEタイプを指定します。URLデコード後、この値がレスポンスの Content-Type ヘッダーにそのまま設定されます。形式がMIMEタイプとして正しくない場合、URLは実行されずエラーが表示されます。 |
mime.type=<fileType> |
<fileType> に拡張子(例:svg, png など)を指定します。拡張子から対応するMIMEタイプを特定し、その値が Content-Type に設定されます。認識できない拡張子の場合、URLは実行されずエラーになります。 |
mime.dataurl |
返却されるデータを「RFC 2397 data URL」として解釈することを示します。返却データが data:application/json,... のような形式である前提で処理され、デコード後の本体データがそのまま返却され、data URLに含まれているMIMEタイプが Content-Type として使われます。data URLとして解析できない場合はエラーになります。 |
クエリパラメータの優先順位と無視されるケース
クエリパラメータが複数指定されている場合、最後に書かれたものが適用されます。
もし mime.xxx のいずれも指定されていない場合、MIMEタイプはERC6860に従って処理されます。
また、もし returns というクエリパラメータが指定されている場合、mime.content、mime.type、mime.dataurl の設定はすべて無視され、Content-Type はERC6860の規定に従います。
ABNF記法で示される構文
定義を形式的に示すために、RFC2234で使われるABNF記法が用いられています。
まず、ERC6860における従来の構文は以下です。
attribute = attrName "=" attrValue
attrName = "returns"
/ "returnTypes"
attrValue = [ "(" [ retTypes ] ")" ]
今回の標準では、これにMIME関連の属性が加わります。
attribute = retAttr / mimeCAttr / mimeTAttr / mimeDAttr
retAttr = retAttrName "=" retAttrValue
retAttrName = "returns"
/ "returnTypes"
retAttrValue = [ "(" [ retTypes ] ")" ]
mimeCAttr = "mime.content=" mimeCAttrVal
mimeCAttrVal = # ABNF of MIME type as in RFC 6838
mimeTAttr = "mime.type=" 1*( ALPHA / DIGIT )
mimeDAttr = "mime.dataurl"
新しい構文により、returnsとreturnTypesに加えて、MIMEタイプに関する3つの指定方法が正式に扱われるようになっています。
例
ここでは具体例を挙げながら、各クエリパラメータがどのように解釈されるかを説明します。
例1:mime.content による MIMEタイプの直接指定
web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289?mime.content=image/svg%2Bxml
コントラクトは auto モードです。
指定された mime.content=image/svg+xml が Content-Type に設定されます。
例2:mime.type による拡張子からの判定
web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289?mime.type=svg
コントラクトは auto モードです。
mime.type=svg から MIMEタイプが解決され、image/svg+xml が Content-Type として設定されます。
例3:mime.dataurl によるdata URLのデコード
web3://0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7/tokenURI/100?mime.dataurl
auto モードのコントラクトが戻すデータは以下のようなdata URL形式です。
data:application/json,["xx"]
mime.dataurl が指定されているため、返却データはdata URLとして解析・デコードされます。
結果として返されるデータは ["xx"] になり、Content-Type には application/json が設定されます。
補足
ERC6860では、3つの異なるクエリパラメータを用意しています。
これは、ひとつのパラメータに複数の形式を詰め込むと、開発者や利用者が「このURLは最終的にどのMIMEタイプになるのか」を判断しづらくなるためです。
mime.content、mime.type、mime.dataurl の3種類が分かれていることで、URLを見るだけで意図が明確になります。
例えば、mime.content= があれば「MIMEタイプを直接指定している」、mime.type= なら「拡張子から判断する」、mime.dataurl なら「返却データをdata URLとして扱う」ことがすぐにわかります。
さらに、auto モードではクエリパラメータがEVMメッセージ(calldata など)を構築する時に影響を与えません。
そのため、新しいパラメータを追加しても既存仕様を壊すことがなく、安全に拡張できます。
セキュリティ
これらの新しいクエリパラメータは、クロスサイトスクリプティング(XSS)を誘発する可能性があります。
悪意のある攻撃者が、スマートコントラクトが返す文字列やバイト列を自分の思うように操作できると、そのデータをHTMLとして解釈させるURLを組み上げ、被害者に送信することができます。
もし web3:// のホスト名が広く知られており信頼されている場合、被害者はそのURLを安全だと勘違いし、攻撃に気づかずに開いてしまうおそれがあります。
こうした攻撃で可能になる行動は幅広く、例えば以下のようなものがあります。
| 攻撃内容 | 説明 |
|---|---|
| Webストレージのデータ取得 | cookie、localStorage、sessionStorage、indexedDB などの内容を盗み出し、攻撃者に送信できます。 |
| ウォレット操作の誘発 | JavaScript 経由で署名要求やトランザクション確認を強制的に表示させることができます。 |
クロスサイトスクリプティングはHTTPの世界では古くから存在する一般的な攻撃手法です。
開発者は当然注意すべきですが、web3:// の仕組みでは「URL側からMIMEタイプを指定できる」点が通常と異なるため、特に注意が必要です。
そのため、auto モードで動作するウェブサイトは安易に使わないことが推奨されます。
また、こうした攻撃ベクトルは十分に説明し、利用者や開発者が理解して対策を取れるようにすることが重要です。
引用
Qi Zhou (@qizhou), Nicolas Deschildre (@nand2), "ERC-7087: MIME type for Web3 URL in Auto Mode [DRAFT]," Ethereum Improvement Proposals, no. 7087, May 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7087.
最後に
今回は「ブラウザが誤解釈しないよう、Web3 URLの返却データに適切なMIMEタイプを与える仕組みを提案しているERC6860の拡張仕様を提案しているERC7087」についてまとめてきました!
いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!