Help us understand the problem. What is going on with this article?

[Elm] 危険🐐img onerror芸

More than 1 year has passed since last update.

本記事では、The Elm Architecture を容易に破壊しうる闇の技術「img onerror芸」をご紹介します。
原則として「img onerror芸」は使わないに越したことはないですが、危険🐐スクリプト芸のように、ごくまれにメリットがデメリットを上回る場合があるかもしれません。

「危険🐐スクリプト芸」と同じく基本的に飛び道具的な内容のため、乱用は絶対にさけましょう。
The Elm Architecture の脆弱性をついたような技法なので何が起きても知りません。
以下の内容はバージョン0.18 を想定しています。

img onerror 芸とは

XSS脆弱性をつくときによく使われる

<img src="1" onerror="alert(1)">

を悪用した非推奨テクニックです。

念のため上記のHTMLを説明しておくと、img タグの src に存在しないパスを設定することで意図的に onerror を発火させ、任意のJSを実行する手法です。

では、Elmで以下のようなViewを作成するとどうなるでしょうか?

{-| An evil view that sends `Msg` on rendering.
-}
onRenderThis : msg -> Html msg
onRenderThis msg =
    Html.img
        [ Attributes.src ""
        , Events.on "error" <| Json.succeed msg
        ]
        []

上記のテクニックと同じように、この img タグが画面上に描画された瞬間に Events.on "error" の部分が発火するため、
「あるViewが実際に画面に描画された瞬間に任意の Msg を飛ばして update 関数を実行する」というハックが可能になります。

The Elm Architecture をこわすので絶対にやらない方が良いですね。
Elm 0.23 くらいで使用禁止になるかもしれません。

elm-evil-sendmsg というライブラリになっているので、どうしても使いたいときにはこれを使うとお手軽でいいでしょう。

つかいどころ

もう一度言います。 使うべきではありません。
ちょっとだけ便利になるかもしれないパターンは、たとえば以下のようなユースケースでしょうか?

特定のDOMに対して port でJSのコードを適用したい場合

DOM更新後にJSを実行する方法 がちゃんと用意されているのでこちらを使いましょう。
でも、DOMを作成するタイミングがあまりにも複雑で、update 関数のどこでそのDOMを作成するかがわかりにくい場合、img onerror芸を使うとちょっとすっきりします。
でも、すっきりするだけでそんなバッドハックを使ったらダメです。
update 関数の書き方を工夫すればいくらでもすっきり書けるはずです。

Model の値を監視する

Evil.SendMsg.when を使えば、Modelの特定の値を監視して、閾値を超えたら Msg を発行するような実装が可能になります。

elm-evil-sendmsgのデモでは、さくらちゃんがデレる閾値の検出に Evil.SendMsg.when を利用しています。

でも、update 関数で常に対象の値をチェックしたら同じことができます。
ちょっと簡単になるからってこんなバッドハックを使ったらダメです。

ボタンを押す処理を代替する

elm-evil-sendmsgのデモでは、さくらちゃんとの会話を進めるために「Click to Next」のボタンを押す必要がありますが、「Auto」ボタンを押すと自動で会話が進んでいきます。
この挙動を

  • ユーザーの行動によって Msg を発行するボタン
  • 画面に表示された瞬間に Msg を発行するボタン

と抽象化して考えるととてもすっきり実装できます。

でも、これも本当は update 関数で会話を進めるときに Auto ボタンが押されているかチェックして動作を分岐させるのが正しいやり方です。
「抽象化できてるオレかっけー」と思ってバッドハックを使うのはダメです。

sakura.jpg
さくらちゃんにご飯をあげる

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away