Skip to content

Commit 03c9357

Browse files
committed
Only allow UnsafeHtml values for :dangerouslySetInnerHTML
1 parent 07bc86c commit 03c9357

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

src/reagent/core.cljs

+8
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,11 @@
372372
:superseded-by "reagent.dom/render"}
373373
[& _]
374374
(throw (js/Error. "Reagent.core/render function was moved to reagent.dom namespace in Reagent v1.0.")))
375+
376+
(defn unsafe-html
377+
"Create a tagged value for use with :dangerouslySetInnerHTML.
378+
Reagent doesn't allow other values to be used with the property,
379+
to ensure EDN and Transit data can't be used to accidentally
380+
create arbitrary HTML."
381+
[s]
382+
(tmpl/UnsafeHTML. s))

src/reagent/impl/template.cljs

+11-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
[reagent.debug :refer-macros [dev? warn]]
1010
[goog.object :as gobj]))
1111

12+
(deftype UnsafeHTML [__html])
13+
1214
;; From Weavejester's Hiccup, via pump:
1315
(def ^{:doc "Regular expression that parses a CSS-style id and class
1416
from a tag name."}
@@ -118,10 +120,15 @@
118120
(let [class (:class props)
119121
props (-> props
120122
(cond-> class (assoc :class (util/class-names class)))
121-
(set-id-class id-class))]
122-
(if (.-custom id-class)
123-
(convert-custom-prop-value props)
124-
(convert-prop-value props))))
123+
(set-id-class id-class))
124+
^js js-props (if (.-custom id-class)
125+
(convert-custom-prop-value props)
126+
(convert-prop-value props))]
127+
;; Ensure only tagged values are used for dangerouslySetInnerHTML
128+
(when-let [d (and js-props (.-dangerouslySetInnerHTML js-props))]
129+
(when-not (instance? UnsafeHTML d)
130+
(js-delete js-props "dangerouslySetInnerHTML")))
131+
js-props))
125132

126133
;;; Conversion from Hiccup forms
127134

test/reagenttest/testreagent.cljs

+10-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@
308308
(as-string [:div.bar [:p "foo"]])))
309309
(is (= "<div class=\"bar\"><p>foobar</p></div>"
310310
(as-string [:div.bar {:dangerously-set-inner-HTML
311-
{:__html "<p>foobar</p>"}}]))))
311+
(r/unsafe-html "<p>foobar</p>")}]))))
312312

313313
(u/deftest ^:dom test-return-class
314314
(let [ran (atom 0)
@@ -1525,3 +1525,12 @@
15251525
16))))
15261526
[really-simple]]
15271527
u/fn-compiler)))))))
1528+
1529+
(u/deftest test-unsafe-html
1530+
(testing "Regular value is ignored"
1531+
(is (= "<div></div>"
1532+
(as-string (r/as-element [:div {:dangerouslySetInnerHTML {:__html "<img/>"}}])))))
1533+
1534+
(testing "Tagged value is allowed"
1535+
(is (= "<div><img/></div>"
1536+
(as-string (r/as-element [:div {:dangerouslySetInnerHTML (r/unsafe-html "<img/>")}]))))))

0 commit comments

Comments
 (0)