LoginSignup
0
0

More than 5 years have passed since last update.

Hiccup を使うときはエスケープ問題にご注意

Posted at

先日アドベントカレンダーで書いたといったドキュメントが思いの外好評ぽかったので安心しているところですが、一点だけ注意しないといけないことがあります。

とりあえず以下のようなコードを書いてみます。

(ns demo.core
  (:require [hiccup.core :as h]
            [immutant.web :as web]
            [ring.util.response :as res]))

(defn handler [req]
  (let [user-input "<script>alert('(\\\\( ⁰⊖⁰)/)')</script>"]
    (-> [:div user-input]
        h/html
        res/response
        (res/content-type "text/html; charset=utf-8"))))

(web/run #'handler {:port 3000})

するとあら不思議。

piyopiyo.png

このようにアラートが画面に出てしまいます。これは Hiccup が自動的に文字列をエスケープしてくれないためです。ではどうしたら良いかというと次のようにします。

(defn handler [req]
  (let [user-input "<script>alert('(\\\\( ⁰⊖⁰)/)')</script>"]
    (-> [:div (h/h user-input)] ;; hiccup.core/h を使うことで文字列をエスケープすることが出来る
        h/html
        res/response
        (res/content-type "text/html; charset=utf-8"))))

piyoooo.png

はい、これで安心ですね。

ホビー/学習用途で Hiccup を使う場合、そこまで気にする必要がないかもしれませんが実プロダクトで使うときには気を付けてください。

補足

自動的にエスケープしてくれるテンプレートエンジンが多い中、 Hiccup のような存在は珍しいと思います。この問題は Issue にもあがっているのですが、 Hiccup 自身を根幹から作り変えないと対応出来ない上に対応中のブランチも開発が止まっているようでなかなか改善されないでいます。

Hiccup のような記述方法は使いたいけど、いちいちエスケープをするのが嫌だ、という方は次のように Enlive を使うことで問題を解決できます。

resources/template/main.html
<!doctype>
<html>
    <body>
    </body>
</html>

HTML のテンプレートを用意しておいて…

(ns demo.core
  (:require [immutant.web :as web]
            [net.cgrand.enlive-html :as html]
            [ring.util.response :as res]))

(html/deftemplate layout "template/main.html" [content]
  [:body] (html/content content))

(defn handler [req]
  (let [user-input "<script>alert('(\\\\( ⁰⊖⁰)/)')</script>"]
    (-> [:div user-input]
        html/html
        layout
        res/response
        (res/content-type "text/html; charset=utf-8"))))

こうすれば、 Hiccup の記述力を失わずにセキュアなコードを書くことができます。ベター Hiccup としても使える Enlive は優秀です。

(ドキュメントの方は後で注意書きを足しておきます)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0