SVGヤバイ 2013冬
Chrome 31がStableになって久しい。何が変わったのか思い出せないんだけど、ひとつだけ覚えてるのがこちら。
WebKitのパッチをマージしたものらしい。ちょっとずつ離れているらしいけど、まだお互い共有できるパッチもあるんだね。
さて、このパッチによって、CanvasでSVG画像をdrawImage()
などで描画したとき、条件によってはそのCanvasがtaintされなくなった。
Tainted Canvasとは
CanvasにはdrawImage()
など、画像をCanvasに描画するメソッドがある。ここで、スクリプトとsame-originではないとこにある画像を描画してしまうと、セキュリティ上の都合からCanvasが“tainted”(「汚染」)という扱いになり、getImageData()
, toDataURL()
, toBlob()
などができない。
ハックではない正攻法な対策としては、画像の配置場所をスクリプトとsame-originなところにするのが楽か。もしくはCORSのヘッダを設定してその許可したorigin以下に画像を配置し、それから画像にcrossorigin
属性(DOMの場合はcrossOrigin
)を指定するなんてやり方もある。詳しくはMDNのドキュメント参照のこと。日本語訳がある。
こんなニッチなの誰が訳したんだと思ったら自分だった…記憶がまったくない。
きたないSVG
さて、originまわりが良くなってもtainted扱いになるなんて場合がある。SVG画像だ。SVGは中にスクリプトや画像を書けちゃうので、危ないと判断されてWebKit/Blinkではこれまでどうあがいてもtainted扱いとなっていた。
あー説明めんどくさい…と思ってたらgyuqueさんが2年半前に同じことを書かれていた。しかもデモつき。なんと。
今回のパッチで、SVG画像が内部で画像を呼んでない場合、そのSVG画像をdrawImage()
で読み込んでもtainted扱いにならなくなった。Chrome 31で見てみたところ、一番右の列がすべて「OK」となったのを確認。
マミさんは死んだ。
例で使われている画像的には良い気がしないけど、Webプラットフォーム的には良い変更だ。
試してないけど、SVG画像の中に<svg:image>
があるとアウトになるんだろう。
Geckoではだいぶ前からOKだったらしい
Firefoxで見たところこちらもOK(マミさんは死ぬけど)。2011年5月時点ではGeckoでもダメだったようだけど、Geckoでは2011年末に修正され、Firefox 11から使えていたらしい。今回Blinkもサポートされるのでカバー範囲が広がったけど、SafariはSafari 8になるだろう。来年かー