Posted at

Elmで生のHTMLをそのまま表示させる


ElmのXSS対策

Elmは非常に堅牢なアプリケーション開発に向いた親切でとても良くできた言語で、通常はXSS脆弱性を引き起こすことができないようになっています。

そのため、もちろん文字列として持っている生のHTMLを表示しようとして

import Html exposing (Html)

view : Model -> Html Msg
view model =
div
[]
[ text raw
]

raw : String
raw = """
<div>
こんにちはこんにちは
</div>
"""

このようにしても、実際には

<div>

&lt;div&gt;こんにちはこんにちは&lt;/div&gt;
</div>

こういうHTML相当のものに変換されます。


生のHTMLを埋め込みたくなったら

じゃあ、生のHTMLをそのままHTMLとして埋め込みたくなったらどうしたらいいのでしょうか?

まず大前提として、生のHTMLは生肉と同じくらい危険です。

生肉なんてヤギでも食べません。

(草食動物だから)

sakura.jpg

生HTMLを表示したくなったら自分の設計を疑うべきです。

全然関係ないけど、アニサキスとサニタイズってなんか似てるよね。


それでもやりたい

Elm 0.18 であれば危険🐐スクリプト芸を使うことができましたが、あまりにも危険なので0.19では禁止されました。

Elm 0.19ではあきらめるしかないのでしょうか?

(再三いいますが、普通はあきらめて設計を見直したほうが良いと思います)

なんと、裏技があるのです。

Elmのアプリ内でコードをハイライト表示するでも使ったelm-explorations/markdownを使います。

これはもともとマークダウンのテキストを Elmの Html型に変換する機能を提供しますが、その変換時に「HTMLをそのままサニタイズしないでHTML型に変換する」というオプションが用意されてます。

いぇーい。

sakura2.jpg

それがOptions型sanitizeっていうオプションです。

これを Falseにして toHtmlWith関数で Html型に変換してやれば良いんです。

先ほどの例はこうなります。

import Html exposing (Html)

import Markdown exposing (defaultOptions)

view : Model -> Html Msg
view model =
Markdown.toHtmlWith
{ defaultOptions
| sanitize = False
}
[]
raw

raw : String
raw = """
<div>
こんにちはこんにちは
</div>
"""

わーい かんたん!

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

さくらちゃんをもっと見る

他の記事を見る

end.jpg