Skip to content

Commit 3c749e1

Browse files
committed
Only allow UnsafeHtml values for :dangerouslySetInnerHTML
1 parent 07bc86c commit 3c749e1

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

src/reagent/core.cljs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,13 @@
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. Reagent doesn't
378+
allow other values to be used with the property, to ensure data from external
379+
sources (using EDN or Transit) can't be used to accidentally create arbitrary
380+
HTML.
381+
382+
See doc/Security.md"
383+
[s]
384+
(tmpl/UnsafeHTML. s))

src/reagent/impl/template.cljs

Lines changed: 12 additions & 4 deletions
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 [s])
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,16 @@
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+
(if (instance? UnsafeHTML d)
130+
(set! (.-dangerouslySetInnerHTML js-props) #js {:__html (.-s d)})
131+
(js-delete js-props "dangerouslySetInnerHTML")))
132+
js-props))
125133

126134
;;; Conversion from Hiccup forms
127135

test/reagenttest/testreagent.cljs

Lines changed: 10 additions & 1 deletion
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)