From 6bc0bd84afb9ca1e594c6632288bde3ddc30f4f9 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sun, 8 Jan 2023 20:39:27 +0000 Subject: [PATCH] Allowed markdown in footer of status page Markdown support has been added using the marked module. To secure against XSS attacks, DOMPurify is used to sanitize the generated HTML before it is loaded on the page. Signed-off-by: Matthew Nickson --- package-lock.json | 28 ++++++++++++++++++++++++++++ package.json | 2 ++ src/languages/en.js | 1 + src/pages/StatusPage.vue | 12 +++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 7e88d1269..3efce2541 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "compare-versions": "~3.6.0", "compression": "~1.7.4", "dayjs": "~1.11.5", + "dompurify": "^2.4.3", "express": "~4.17.3", "express-basic-auth": "~1.2.1", "express-static-gzip": "~2.1.7", @@ -38,6 +39,7 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "limiter": "~2.1.0", + "marked": "^4.2.5", "mqtt": "~4.3.7", "mssql": "~8.1.4", "mysql2": "~2.3.3", @@ -6499,6 +6501,11 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz", + "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==" + }, "node_modules/domutils": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", @@ -12185,6 +12192,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", + "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -22155,6 +22173,11 @@ "domelementtype": "^2.3.0" } }, + "dompurify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz", + "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==" + }, "domutils": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", @@ -26299,6 +26322,11 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "marked": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", + "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==" + }, "mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", diff --git a/package.json b/package.json index ebe305f92..fcda34371 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "compare-versions": "~3.6.0", "compression": "~1.7.4", "dayjs": "~1.11.5", + "dompurify": "^2.4.3", "express": "~4.17.3", "express-basic-auth": "~1.2.1", "express-static-gzip": "~2.1.7", @@ -93,6 +94,7 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "limiter": "~2.1.0", + "marked": "^4.2.5", "mqtt": "~4.3.7", "mssql": "~8.1.4", "mysql2": "~2.3.3", diff --git a/src/languages/en.js b/src/languages/en.js index 8d07db6dc..5824ea4ab 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -675,4 +675,5 @@ export default { "General Monitor Type": "General Monitor Type", "Passive Monitor Type": "Passive Monitor Type", "Specific Monitor Type": "Specific Monitor Type", + markdownSupported: "Markdown syntax supported", }; diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 6cecf6682..6fbbe69a1 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -26,6 +26,9 @@
+
+ {{ $t("markdownSupported") }} +
@@ -279,7 +282,9 @@ - + + +

{{ $t("Powered by") }} {{ $t("Uptime Kuma" ) }} @@ -310,6 +315,8 @@ import ImageCropUpload from "vue-image-crop-upload"; import { PrismEditor } from "vue-prism-editor"; import "vue-prism-editor/dist/prismeditor.min.css"; // import the styles somewhere import { useToast } from "vue-toastification"; +import { marked } from "marked"; +import DOMPurify from "dompurify"; import Confirm from "../components/Confirm.vue"; import PublicGroupList from "../components/PublicGroupList.vue"; import MaintenanceTime from "../components/MaintenanceTime.vue"; @@ -477,6 +484,9 @@ export default { return this.overallStatus === STATUS_PAGE_MAINTENANCE; }, + footerHTML() { + return DOMPurify.sanitize(marked(this.config.footerText)); + }, }, watch: {