From cfbe3ef10fa67b55321be5fc1b995f42790a0662 Mon Sep 17 00:00:00 2001 From: Waldemar Mazurek Date: Thu, 10 Oct 2024 11:10:24 +0200 Subject: [PATCH] Fixes client potential XSS issue (#3976) --- website/landingpage/dev/package-lock.json | 12 ++++ website/landingpage/dev/package.json | 3 +- website/landingpage/dev/src/assets/js/app.js | 72 +++++++++----------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/website/landingpage/dev/package-lock.json b/website/landingpage/dev/package-lock.json index 0e6332fd37..8d2606cbd0 100644 --- a/website/landingpage/dev/package-lock.json +++ b/website/landingpage/dev/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "dompurify": "^3.1.7", "feed": "^4.2.2", "foundation-sites": "^6.8.1", "jquery": "^3.7.1", @@ -3733,6 +3734,12 @@ "node": ">= 0.8.0" } }, + "node_modules/dompurify": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", + "license": "(MPL-2.0 OR Apache-2.0)" + }, "node_modules/duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -13080,6 +13087,11 @@ "integrity": "sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==", "dev": true }, + "dompurify": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", diff --git a/website/landingpage/dev/package.json b/website/landingpage/dev/package.json index a3bf34fceb..edcb667cb7 100644 --- a/website/landingpage/dev/package.json +++ b/website/landingpage/dev/package.json @@ -10,6 +10,7 @@ }, "license": "MIT", "dependencies": { + "dompurify": "^3.1.7", "feed": "^4.2.2", "foundation-sites": "^6.8.1", "jquery": "^3.7.1", @@ -68,7 +69,7 @@ "marked": "^4.0.10", "highlight.js": "^11.0.0" }, - "browser-sync" : { + "browser-sync": { "localtunnel": { "axios": "1.6.0" } diff --git a/website/landingpage/dev/src/assets/js/app.js b/website/landingpage/dev/src/assets/js/app.js index 22908354f4..e89add1349 100644 --- a/website/landingpage/dev/src/assets/js/app.js +++ b/website/landingpage/dev/src/assets/js/app.js @@ -1,4 +1,5 @@ import $ from 'jquery'; +import DOMPurify from 'dompurify'; import 'what-input'; // Foundation JS relies on a global varaible. In ES6, all imports are hoisted @@ -23,10 +24,7 @@ if (document.getElementById('num')) { let number = 10; let counter = setInterval(function() { if (number > 0) { - document.getElementById('num').innerHTML = String(--number).padStart( - 2, - '0' - ); + document.getElementById('num').innerHTML = String(--number).padStart(2, '0'); } else { clearInterval(counter); } @@ -75,9 +73,7 @@ if (!String.prototype.repeat) { // main part. But anyway, most current (August 2014) browsers can't handle // strings 1 << 28 chars or longer, so: if (str.length * count >= 1 << 28) { - throw new RangeError( - 'repeat count must not overflow maximum string size' - ); + throw new RangeError('repeat count must not overflow maximum string size'); } var maxCount = str.length * count; count = Math.floor(Math.log(count) / Math.log(2)); @@ -95,9 +91,7 @@ if (!String.prototype.repeat) { let listCounter = 0; if (document.getElementById('social-list')) { - let listItems = document - .getElementById('social-list') - .getElementsByTagName('a'); + let listItems = document.getElementById('social-list').getElementsByTagName('a'); setActiveLinkOnHover(listItems); setActiveLinkOnKeyboardClick(listItems); @@ -157,37 +151,39 @@ var backToBlog = $('#back-to-blog'); //variables for load more blogs functionality var loadMoreBlogsBtn = $('#load-more-blogs-btn'); var backToTopBtn = $('#back-to-top-btn'); -var filesAmount = $('#blog-chunks-data').data("chunk-total"); //count amount of all blogs files -var chunksMinBlogLoadAmount = $('#blog-chunks-data').data("chunk-step"); //amount of blogs to be visible on first load +var filesAmount = $('#blog-chunks-data').data('chunk-total'); //count amount of all blogs files +var chunksMinBlogLoadAmount = $('#blog-chunks-data').data('chunk-step'); //amount of blogs to be visible on first load var chunkCounter = 0; loadMoreBlogsBtn.on('click', function() { fetch('blog-chunks/blog-chunk' + chunkCounter + '.html', { method: 'GET' - }).then(response => { - if (response.ok) { - response.text().then(response => { - $('#blog-chunk').append(response); - chunkCounter = chunkCounter + chunksMinBlogLoadAmount; - let chunksWrapperDIV = $('#blog-chunk div.blog-entry:nth-child(' + chunkCounter + ')'); - - //ids for a smooth scroll to particular new div - chunksWrapperDIV.attr('id', 'chunk-number' + chunkCounter); - loadMoreBlogsBtn.attr('href', '#chunk-number' + chunkCounter); - - let currentVisibleBlogs = chunkCounter + chunksMinBlogLoadAmount; - if (currentVisibleBlogs >= filesAmount ){ - loadMoreBlogsBtn.addClass('hide'); - backToTopBtn.removeClass('hide'); - } else if (filesAmount === undefined) { - loadMoreBlogsBtn.hide(); - } - }); - } else { - console.log("Can not fetch the chunk"); - } - }).catch(error => { - console.log("No blog-chunks is available", error); + }) + .then(response => { + if (response.ok) { + response.text().then(response => { + $('#blog-chunk').append(DOMPurify.sanitize(response)); + chunkCounter = chunkCounter + chunksMinBlogLoadAmount; + let chunksWrapperDIV = $('#blog-chunk div.blog-entry:nth-child(' + chunkCounter + ')'); + + //ids for a smooth scroll to particular new div + chunksWrapperDIV.attr('id', 'chunk-number' + chunkCounter); + loadMoreBlogsBtn.attr('href', '#chunk-number' + chunkCounter); + + let currentVisibleBlogs = chunkCounter + chunksMinBlogLoadAmount; + if (currentVisibleBlogs >= filesAmount) { + loadMoreBlogsBtn.addClass('hide'); + backToTopBtn.removeClass('hide'); + } else if (filesAmount === undefined) { + loadMoreBlogsBtn.hide(); + } + }); + } else { + console.log('Can not fetch the chunk'); + } + }) + .catch(error => { + console.log('No blog-chunks is available', error); }); }); @@ -197,5 +193,5 @@ if (backToBlog.length && document.referrer.indexOf('/blog/overview') !== -1 && w e.preventDefault(); e.stopPropagation(); history.back(); -}); -} \ No newline at end of file + }); +}