From 6bc0bd84afb9ca1e594c6632288bde3ddc30f4f9 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sun, 8 Jan 2023 20:39:27 +0000 Subject: [PATCH 1/5] 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 7e88d126..3efce254 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 ebe305f9..fcda3437 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 8d07db6d..5824ea4a 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 6cecf668..6fbbe69a 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: { From 852a0885299bf3eeb2927c45675c8d578d18cb63 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sun, 8 Jan 2023 20:46:18 +0000 Subject: [PATCH 2/5] Added mardown support for incident Signed-off-by: Matthew Nickson --- src/pages/StatusPage.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 6fbbe69a..ab7ed69b 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -151,7 +151,12 @@ {{ $t("Content") }}: - + +

+ {{ $t("markdownSupported") }} +
+ +
@@ -484,6 +489,10 @@ export default { return this.overallStatus === STATUS_PAGE_MAINTENANCE; }, + incidentHTML() { + return DOMPurify.sanitize(marked(this.incident.content)); + }, + footerHTML() { return DOMPurify.sanitize(marked(this.config.footerText)); }, From 80f2d6e2a7229147fe2cd055faf7df457de8a017 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Sun, 8 Jan 2023 20:54:16 +0000 Subject: [PATCH 3/5] Added markdown support for maintenance Signed-off-by: Matthew Nickson --- src/pages/EditMaintenance.vue | 3 +++ src/pages/StatusPage.vue | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/pages/EditMaintenance.vue b/src/pages/EditMaintenance.vue index d668d1ad..da7dee5a 100644 --- a/src/pages/EditMaintenance.vue +++ b/src/pages/EditMaintenance.vue @@ -21,6 +21,9 @@ +
+ {{ $t("markdownSupported") }} +
diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index ab7ed69b..3b89ed83 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -244,7 +244,8 @@ class="shadow-box alert mb-4 p-3 bg-maintenance mt-4 position-relative" role="alert" >

{{ maintenance.title }}

-
{{ maintenance.description }}
+ +
@@ -855,6 +856,15 @@ export default { this.config.domainNameList.splice(index, 1); }, + /** + * Generate sanitized HTML from maintenance description + * @param {string} description + * @returns {string} Sanitized HTML + */ + maintenanceHTML(description) { + return DOMPurify.sanitize(marked(description)); + }, + } }; From a8f0f1d872b359e53efada97ab8f9e84a72b8cad Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Wed, 1 Feb 2023 15:51:33 +0800 Subject: [PATCH 4/5] Merge manually and remove to devDependencies --- package-lock.json | 36 ++++++++++++++++++++++++++++++++++-- package.json | 4 ++-- src/lang/en.json | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9da62968..c1e2645f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "uptime-kuma", - "version": "1.19.5", + "version": "1.19.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "1.19.5", + "version": "1.19.6", "license": "MIT", "dependencies": { "@grpc/grpc-js": "~1.7.3", @@ -88,10 +88,12 @@ "cypress": "^10.1.0", "delay": "^5.0.0", "dns2": "~2.0.1", + "dompurify": "~2.4.3", "eslint": "~8.14.0", "eslint-plugin-vue": "~8.7.1", "favico.js": "~0.3.10", "jest": "~27.2.5", + "marked": "~4.2.5", "postcss-html": "~1.5.0", "postcss-rtlcss": "~3.7.2", "postcss-scss": "~4.0.4", @@ -7800,6 +7802,12 @@ "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==", + "dev": true + }, "node_modules/domutils": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", @@ -13613,6 +13621,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", + "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "dev": true, + "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", @@ -24871,6 +24891,12 @@ "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==", + "dev": true + }, "domutils": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", @@ -29100,6 +29126,12 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "marked": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", + "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "dev": true + }, "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 1dc87f08..7a148ec2 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ "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", @@ -98,7 +97,6 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "limiter": "~2.1.0", - "marked": "^4.2.5", "mongodb": "~4.13.0", "mqtt": "~4.3.7", "mssql": "~8.1.4", @@ -147,9 +145,11 @@ "cypress": "^10.1.0", "delay": "^5.0.0", "dns2": "~2.0.1", + "dompurify": "~2.4.3", "eslint": "~8.14.0", "eslint-plugin-vue": "~8.7.1", "favico.js": "~0.3.10", + "marked": "~4.2.5", "jest": "~27.2.5", "postcss-html": "~1.5.0", "postcss-rtlcss": "~3.7.2", diff --git a/src/lang/en.json b/src/lang/en.json index cab3dcea..072e0720 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -25,6 +25,7 @@ "General Monitor Type": "General Monitor Type", "Passive Monitor Type": "Passive Monitor Type", "Specific Monitor Type": "Specific Monitor Type", + "markdownSupported": "Markdown syntax supported", "pauseDashboardHome": "Pause", "Pause": "Pause", "Name": "Name", From 3819266fa83605fac57eed55bc003bb07f7f5c50 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Thu, 2 Feb 2023 17:55:40 +0000 Subject: [PATCH 5/5] Fixed style of links in markdown Signed-off-by: Matthew Nickson --- src/assets/app.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/assets/app.scss b/src/assets/app.scss index 7da76fff..f550406f 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -35,6 +35,11 @@ textarea.form-control { color: $maintenance !important; } +.incident a, +.bg-maintenance a { + color: inherit; +} + .list-group { border-radius: 0.75rem; @@ -248,6 +253,11 @@ optgroup { } } + .incident a, + .bg-maintenance a { + color: inherit; + } + .form-control, .form-control:focus, .form-select,