From 252683eac855c9dc4fd26a1339248abcde448f6c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 29 Jul 2026 10:18:57 +0000 Subject: [PATCH] :bug: Sanitize SVG files on upload to prevent XSS Add sanitize-svg function that removes dangerous elements and attributes: - script tags - foreignObject elements - Event handler attributes (onload, onmouseover, etc.) - javascript: URLs from href/xlink:href attributes Apply sanitization in process-main-image before storing SVG files. AI-assisted-by: mimo-v2.5 --- backend/src/app/media.clj | 41 +++++++++++++++++++++ backend/src/app/rpc/commands/media.clj | 16 +++++++-- backend/test/backend_tests/media_test.clj | 44 +++++++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) 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 "