Просмотр исходного кода

Merge commit from fork

fix: sanitize markdown HTML from CSS classes & styles
El RIDO 1 месяц назад
Родитель
Сommit
20cecb6546
3 измененных файлов с 20 добавлено и 6 удалено
  1. 1 0
      CHANGELOG.md
  2. 18 5
      js/privatebin.js
  3. 1 1
      lib/Configuration.php

+ 1 - 0
CHANGELOG.md

@@ -15,6 +15,7 @@
 * FIXED: Prevent browsers guessing MIME types on JSON(LD) API responses (#164)
 * FIXED: Prevent browsers guessing MIME types on JSON(LD) API responses (#164)
 * FIXED: Insert quoted base path into JSON-LD documents
 * FIXED: Insert quoted base path into JSON-LD documents
 * FIXED: Several potential issues in handling comment files (#1901)
 * FIXED: Several potential issues in handling comment files (#1901)
+* FIXED: Sanitize Markdown HTML from CSS classes & styles
 
 
 ## 2.0.6 (2026-08-08)
 ## 2.0.6 (2026-08-08)
 * CHANGED: Stricter MIME type validation, divergent files get no preview and forced download link
 * CHANGED: Stricter MIME type validation, divergent files get no preview and forced download link

+ 18 - 5
js/privatebin.js

@@ -56,7 +56,7 @@ window.PrivateBin = (function () {
      */
      */
     const purifyHtmlConfig = {
     const purifyHtmlConfig = {
         ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
         ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
-        ALLOWED_ATTR: ['href', 'id', 'target', 'rel', 'class', 'style'],
+        ALLOWED_ATTR: ['href'],
         USE_PROFILES: {
         USE_PROFILES: {
             html: true
             html: true
         }
         }
@@ -72,9 +72,8 @@ window.PrivateBin = (function () {
      */
      */
     const purifyHtmlConfigStrictSubset = {
     const purifyHtmlConfigStrictSubset = {
         ALLOWED_URI_REGEXP: purifyHtmlConfig.ALLOWED_URI_REGEXP,
         ALLOWED_URI_REGEXP: purifyHtmlConfig.ALLOWED_URI_REGEXP,
-        ALLOWED_TAGS: ['a', 'i', 'span', 'kbd'],
-        ALLOWED_ATTR: ['href', 'id', 'target', 'rel'],
-        ADD_ATTR: ['target', 'rel']
+        ALLOWED_TAGS: ['a'],
+        ALLOWED_ATTR: ['href']
     };
     };
 
 
     /**
     /**
@@ -89,6 +88,20 @@ window.PrivateBin = (function () {
         }
         }
     };
     };
 
 
+    /**
+     * DOMpurify settings for translated messages, which are allowed to include limited HTML.
+     *
+     * NOTE: The key {@link purifyHtmlConfig.USE_PROFILES} **must not** be included,
+     * as otherwise `USE_PROFILES` takes precedence over {@link purifyHtmlConfigStrictSubset.ALLOWED_TAGS}.
+     *
+     * @private
+     */
+    const purifyTranslationConfig = {
+        ALLOWED_URI_REGEXP: /^(?:https?:)/i, // the only URL expected here is the generated document, so only http & https
+        ALLOWED_TAGS: ['a', 'i', 'span', 'kbd'],
+        ALLOWED_ATTR: ['href', 'id'] // one of the messages contains an id attribute
+    };
+
     /**
     /**
      * URL fragment prefix requiring load confirmation
      * URL fragment prefix requiring load confirmation
      *
      *
@@ -805,7 +818,7 @@ window.PrivateBin = (function () {
 
 
             if (containsHtml) {
             if (containsHtml) {
                 // only allow tags/attributes we actually use in translations
                 // only allow tags/attributes we actually use in translations
-                output = DOMPurify.sanitize(output, purifyHtmlConfigStrictSubset);
+                output = DOMPurify.sanitize(output, purifyTranslationConfig);
             }
             }
 
 
             // if element is given, insert translation
             // if element is given, insert translation

+ 1 - 1
lib/Configuration.php

@@ -124,7 +124,7 @@ class Configuration
             'js/kjua-0.10.0.js'      => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==',
             'js/kjua-0.10.0.js'      => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==',
             'js/legacy.js'           => 'sha512-pRofxsrf5UItjiP22Dcjh3FAcBjF/n7h8U9/W5xqJk17U0N2U1oajhXypq/omo9jhwS1iVGOhWrRepoPeFns+w==',
             'js/legacy.js'           => 'sha512-pRofxsrf5UItjiP22Dcjh3FAcBjF/n7h8U9/W5xqJk17U0N2U1oajhXypq/omo9jhwS1iVGOhWrRepoPeFns+w==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
-            'js/privatebin.js'       => 'sha512-HedKxoytOeYbMzjcN3x7/FW01Moba3U9SZI7Yi3V7CkO7B2wsvmgr8kGeurHW0hZssKxGA/3UZ+3tNdsO4o/UA==',
+            'js/privatebin.js'       => 'sha512-TESkKT3BI8chkAJUlFgIJxnBG/mtgHAKJk0sEMX3l554ohQvEyNjLl5ZFeVhT6jvW3mFIxengHfkc12+MokyJA==',
             'js/purify-3.4.12.js'    => 'sha512-Akf6HnAJZm0sWWWI4gp2GYff0NDnHUB02XJE5S7Hdq/Z5xtMjkuFacsDA8ZtViv1gi+onBxMhEMIaGyQeGxBng==',
             'js/purify-3.4.12.js'    => 'sha512-Akf6HnAJZm0sWWWI4gp2GYff0NDnHUB02XJE5S7Hdq/Z5xtMjkuFacsDA8ZtViv1gi+onBxMhEMIaGyQeGxBng==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
             'js/zlib-1.3.2.js'       => 'sha512-RAhJgxg9siMIA8ky4c10Rc2zUgnK80olHB8Tt1IOYWY4Eh1WmrviQkDn+sgBlb38ZHq3tzufGC41kP360gmosQ==',
             'js/zlib-1.3.2.js'       => 'sha512-RAhJgxg9siMIA8ky4c10Rc2zUgnK80olHB8Tt1IOYWY4Eh1WmrviQkDn+sgBlb38ZHq3tzufGC41kP360gmosQ==',