From 316cce1b26f1ac745ffb51069762b54373797293 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Sat, 20 Dec 2025 10:49:20 +0100 Subject: [PATCH] Enhance content sanitization across various components by integrating 'dompurify' for improved security and update package dependencies in package.json and package-lock.json. --- composables/useSanitizeHtml.js | 26 +++++++ package-lock.json | 28 +++++++ package.json | 2 + pages/cms/newsletter.vue | 3 +- pages/verein/geschichte.vue | 11 ++- pages/verein/satzung.vue | 11 ++- pages/verein/tt-regeln.vue | 11 ++- pages/verein/ueber-uns.vue | 11 ++- scripts/find-membership-values.js | 2 + scripts/inspect-forms.js | 2 + scripts/re-encrypt-data.js | 4 + scripts/set-admin-password.js | 2 + scripts/smoke-test.js | 2 + server/api/cms/satzung-upload.post.js | 2 + server/api/cms/save-csv.post.js | 2 + server/api/config.get.js | 2 + server/api/config.put.js | 2 + server/api/galerie/[id].delete.js | 2 + server/api/galerie/[id].get.js | 22 +++++- server/api/galerie/list.get.js | 2 + server/api/galerie/upload.post.js | 17 ++++- server/api/membership/applications.get.js | 2 + server/api/membership/generate-pdf.post.js | 22 ++++++ server/api/membership/update-status.put.js | 8 ++ server/api/newsletter/[id].delete.js | 2 + server/api/newsletter/[id].put.js | 2 + server/api/newsletter/[id]/send.post.js | 4 + server/api/newsletter/create.post.js | 2 + .../groups/[id]/posts/create.post.js | 6 ++ .../newsletter/groups/[id]/posts/list.get.js | 2 + .../groups/[id]/subscribers/add.post.js | 2 + .../groups/[id]/subscribers/list.get.js | 2 + server/api/newsletter/groups/create.post.js | 2 + server/api/newsletter/groups/list.get.js | 2 + .../api/newsletter/groups/public-list.get.js | 2 + server/api/newsletter/list.get.js | 2 + server/api/newsletter/subscribe.post.js | 2 + .../newsletter/unsubscribe-by-email.post.js | 2 + server/api/personen/[filename].get.js | 13 +++- server/api/personen/upload.post.js | 27 ++++++- .../api/spielplan/download/[filename].get.js | 11 ++- server/api/spielplan/pdf.get.js | 2 + server/utils/auth.js | 2 + server/utils/email-service.js | 2 + server/utils/members.js | 2 + server/utils/news.js | 2 + server/utils/newsletter.js | 2 + server/utils/path-security.js | 75 +++++++++++++++++++ server/utils/termine.js | 2 + 49 files changed, 349 insertions(+), 23 deletions(-) create mode 100644 composables/useSanitizeHtml.js create mode 100644 server/utils/path-security.js diff --git a/composables/useSanitizeHtml.js b/composables/useSanitizeHtml.js new file mode 100644 index 0000000..4cc26a1 --- /dev/null +++ b/composables/useSanitizeHtml.js @@ -0,0 +1,26 @@ +import DOMPurify from 'dompurify' + +/** + * Sanitizes HTML content to prevent XSS attacks + * @param {string} html - The HTML content to sanitize + * @returns {string} - The sanitized HTML + */ +export function useSanitizeHtml(html) { + if (!html || typeof html !== 'string') { + return '' + } + + // DOMPurify sanitizes HTML and removes dangerous content + return DOMPurify.sanitize(html, { + ALLOWED_TAGS: [ + 'p', 'br', 'strong', 'em', 'u', 's', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'ul', 'ol', 'li', 'a', 'img', 'blockquote', 'code', 'pre', 'span', 'div', + 'table', 'thead', 'tbody', 'tr', 'th', 'td' + ], + ALLOWED_ATTR: [ + 'href', 'src', 'alt', 'title', 'class', 'id', 'width', 'height', 'style' + ], + ALLOW_DATA_ATTR: false + }) +} + diff --git a/package-lock.json b/package-lock.json index f549882..a474906 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@pinia/nuxt": "^0.11.2", "@tinymce/tinymce-vue": "^6.3.0", "bcryptjs": "^2.4.3", + "dompurify": "^3.3.1", "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", "nodemailer": "^7.0.9", @@ -26,6 +27,7 @@ }, "devDependencies": { "@nuxtjs/tailwindcss": "^6.11.0", + "@types/dompurify": "^3.0.5", "autoprefixer": "^10.4.0", "dotenv": "^17.2.3", "eslint-plugin-vue": "^10.6.2", @@ -4199,6 +4201,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -4225,6 +4237,13 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@unhead/vue": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.0.19.tgz", @@ -6524,6 +6543,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", diff --git a/package.json b/package.json index c6665eb..61cdbbd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@pinia/nuxt": "^0.11.2", "@tinymce/tinymce-vue": "^6.3.0", "bcryptjs": "^2.4.3", + "dompurify": "^3.3.1", "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", "nodemailer": "^7.0.9", @@ -33,6 +34,7 @@ }, "devDependencies": { "@nuxtjs/tailwindcss": "^6.11.0", + "@types/dompurify": "^3.0.5", "autoprefixer": "^10.4.0", "dotenv": "^17.2.3", "eslint-plugin-vue": "^10.6.2", diff --git a/pages/cms/newsletter.vue b/pages/cms/newsletter.vue index 360622e..625cf30 100644 --- a/pages/cms/newsletter.vue +++ b/pages/cms/newsletter.vue @@ -168,7 +168,7 @@
@@ -770,6 +770,7 @@ import { ref, computed, onMounted } from 'vue' import { Plus, Loader2, Users, Trash2 } from 'lucide-vue-next' import RichTextEditor from '~/components/RichTextEditor.vue' +import { useSanitizeHtml } from '~/composables/useSanitizeHtml' const authStore = useAuthStore() diff --git a/pages/verein/geschichte.vue b/pages/verein/geschichte.vue index 62f3880..069390c 100644 --- a/pages/verein/geschichte.vue +++ b/pages/verein/geschichte.vue @@ -13,9 +13,12 @@