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 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: { 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 6fbbe69a1..ab7ed69b0 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 d668d1ad1..da7dee5a8 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 ab7ed69b0..3b89ed83a 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 9da629687..c1e2645fc 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 1dc87f082..7a148ec2e 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 cab3dcea3..072e07201 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 7da76fff0..f550406fd 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,