diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index 30527857ad..a7e8a565a6 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -124,6 +124,47 @@ (dm/with-open [istream (IOUtils/toInputStream ^String text "UTF-8")] (xml/parse istream secure-parser-factory)))) +(defn- sanitize-svg-element + "Recursively sanitize an SVG element by removing dangerous tags and attributes." + [{:keys [tag attrs content] :as element}] + (when (and (map? element) tag) + (let [dangerous-tags #{:script :foreignObject} + dangerous-attrs-pattern #"(?i)^(on\w+|xmlns:.*)$" + javascript-href-pattern #"(?i)^javascript:"] + (when-not (contains? dangerous-tags tag) + (let [clean-attrs (->> attrs + (remove (fn [[k v]] + (or (re-matches dangerous-attrs-pattern (name k)) + (and (#{:href :xlink:href} k) + (string? v) + (re-find javascript-href-pattern v))))) + (into {})) + clean-content (when content + (->> content + (filter #(or (string? %) (map? %))) + (map (fn [child] + (if (map? child) + (sanitize-svg-element child) + child))) + (filter some?) + vec))] + (cond-> {:tag tag :attrs clean-attrs} + (seq clean-content) (assoc :content clean-content))))))) + +(defn sanitize-svg + "Sanitize SVG content by removing dangerous elements and attributes. + Removes " + result (media/sanitize-svg svg)] + (t/is (not (clojure.string/includes? result "" + result (media/sanitize-svg svg)] + (t/is (not (clojure.string/includes? result "foreignObject"))) + (t/is (not (clojure.string/includes? result "