From 2e03a8452c21bc4699a62997bdfb102398b320a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Z=C3=BCbeyde=20Civelek?= Date: Thu, 27 Nov 2025 13:52:26 +0100 Subject: [PATCH] ckeditor: add source back and sanitize input --- LICENSE | 2 + .../json/cds_deposit/forms/project.json | 3 + .../static/json/cds_deposit/forms/video.json | 3 + .../js/cds_deposit/avc/avc.module.js | 1 + .../js/cds_deposit/ckeditor-sanitizer.js | 77 +++++++++++++++++++ cds/modules/theme/webpack.py | 1 + 6 files changed, 87 insertions(+) create mode 100644 cds/modules/theme/assets/bootstrap3/js/cds_deposit/ckeditor-sanitizer.js diff --git a/LICENSE b/LICENSE index 5b6e7c66c..ae06a7433 100644 --- a/LICENSE +++ b/LICENSE @@ -338,3 +338,5 @@ proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. + +Includes DOMPurify, licensed under the MPL-2.0. diff --git a/cds/modules/deposit/static/json/cds_deposit/forms/project.json b/cds/modules/deposit/static/json/cds_deposit/forms/project.json index 6f8c4d49c..3e107c688 100644 --- a/cds/modules/deposit/static/json/cds_deposit/forms/project.json +++ b/cds/modules/deposit/static/json/cds_deposit/forms/project.json @@ -53,6 +53,9 @@ "Replace", "-", "RemoveFormat" + ], + [ + "Source" ] ], "disableNativeSpellChecker": false, diff --git a/cds/modules/deposit/static/json/cds_deposit/forms/video.json b/cds/modules/deposit/static/json/cds_deposit/forms/video.json index 9ec11f092..136826282 100644 --- a/cds/modules/deposit/static/json/cds_deposit/forms/video.json +++ b/cds/modules/deposit/static/json/cds_deposit/forms/video.json @@ -52,6 +52,9 @@ "Replace", "-", "RemoveFormat" + ], + [ + "Source" ] ], "disableNativeSpellChecker": false, diff --git a/cds/modules/theme/assets/bootstrap3/js/cds_deposit/avc/avc.module.js b/cds/modules/theme/assets/bootstrap3/js/cds_deposit/avc/avc.module.js index ff8abe6ea..bd2c5ec19 100644 --- a/cds/modules/theme/assets/bootstrap3/js/cds_deposit/avc/avc.module.js +++ b/cds/modules/theme/assets/bootstrap3/js/cds_deposit/avc/avc.module.js @@ -28,6 +28,7 @@ import "angular-ui-sortable"; // CKEditor import "ckeditor"; +import "../ckeditor-sanitizer"; import "rr-ng-ckeditor/ng-ckeditor"; import "angular-schema-form-ckeditor/bootstrap-ckeditor"; diff --git a/cds/modules/theme/assets/bootstrap3/js/cds_deposit/ckeditor-sanitizer.js b/cds/modules/theme/assets/bootstrap3/js/cds_deposit/ckeditor-sanitizer.js new file mode 100644 index 000000000..17416f657 --- /dev/null +++ b/cds/modules/theme/assets/bootstrap3/js/cds_deposit/ckeditor-sanitizer.js @@ -0,0 +1,77 @@ +/** + * CKEditor HTML Sanitizer + * Sanitizes HTML content using DOMPurify to prevent XSS attacks + */ +import DOMPurify from "dompurify"; + +// Sanitization config - matches backend allowed tags +var sanitizeConfig = { + ALLOWED_TAGS: [ + "a", + "abbr", + "acronym", + "b", + "blockquote", + "br", + "code", + "col", + "colgroup", + "div", + "table", + "tbody", + "tfoot", + "thead", + "td", + "th", + "tr", + "em", + "h1", + "h2", + "h3", + "h4", + "h5", + "i", + "li", + "ol", + "p", + "pre", + "s", + "span", + "strike", + "strong", + "sub", + "sup", + "u", + "ul", + ], + ALLOWED_ATTR: ["style", "dir", "lang", "color"], + ALLOW_STYLE: true, + ALLOW_DATA_ATTR: false, +}; + +function sanitizeHtml(html) { + if (!html || typeof html !== "string") { + return html; + } + return DOMPurify.sanitize(html, sanitizeConfig); +} + +// Initialize sanitization when CKEditor instances are ready +if (typeof window !== "undefined" && window.CKEDITOR) { + window.CKEDITOR.on("instanceReady", function (ev) { + var editor = ev.editor; + + // Store original getData method + var originalGetData = editor.getData; + + // Sanitize when content is retrieved (before saving) + editor.getData = function (noEvents) { + var data = originalGetData.call(this, noEvents); + if (data) { + return sanitizeHtml(data); + } + return data; + }; + }); +} + diff --git a/cds/modules/theme/webpack.py b/cds/modules/theme/webpack.py index a1d4f03b5..56c80ccf5 100644 --- a/cds/modules/theme/webpack.py +++ b/cds/modules/theme/webpack.py @@ -97,6 +97,7 @@ "angular-schema-form-ckeditor": "git+https://github.com/CERNDocumentServer/cds-videos-angular-schema-ckeditor", "ckeditor": "4.12.1", "rr-ng-ckeditor": "~0.2.1", + "dompurify": "^2.4.5", # needed because ci fails on tests otherwise. not imported in any bundle "semantic-ui-less": "^2.4.1", "vtt.js": "~0.13.0",