From 980e35880f0f7863edbb15acdccef97cc92d6f7f Mon Sep 17 00:00:00 2001 From: SabreCat Date: Mon, 16 May 2022 15:36:09 -0500 Subject: [PATCH] fix(login): sanitize redirect --- website/client/package-lock.json | 38 ++++++++--------- website/client/package.json | 1 + .../components/auth/registerLoginReset.vue | 42 +++++-------------- 3 files changed, 29 insertions(+), 52 deletions(-) diff --git a/website/client/package-lock.json b/website/client/package-lock.json index 5d59e78db4..65381191f1 100644 --- a/website/client/package-lock.json +++ b/website/client/package-lock.json @@ -17309,6 +17309,11 @@ "domelementtype": "1" } }, + "dompurify": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.8.tgz", + "integrity": "sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==" + }, "domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -18805,13 +18810,8 @@ }, "chownr": { "version": "1.1.1", -<<<<<<< HEAD - "resolved": false, - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" -======= "bundled": true, "optional": true ->>>>>>> 9af2289773af196ab1de83de6af54c8732805177 }, "code-point-at": { "version": "1.1.0", @@ -18858,13 +18858,8 @@ }, "fs-minipass": { "version": "1.2.5", -<<<<<<< HEAD - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", -======= "bundled": true, "optional": true, ->>>>>>> 9af2289773af196ab1de83de6af54c8732805177 "requires": { "minipass": "^2.2.1" } @@ -18974,13 +18969,8 @@ }, "minizlib": { "version": "1.2.1", -<<<<<<< HEAD - "resolved": false, - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", -======= "bundled": true, "optional": true, ->>>>>>> 9af2289773af196ab1de83de6af54c8732805177 "requires": { "minipass": "^2.2.1" } @@ -19207,8 +19197,6 @@ "bundled": true, "optional": true }, -<<<<<<< HEAD -======= "tar": { "version": "4.4.8", "bundled": true, @@ -19223,7 +19211,6 @@ "yallist": "^3.0.2" } }, ->>>>>>> 9af2289773af196ab1de83de6af54c8732805177 "util-deprecate": { "version": "1.0.2", "bundled": true, @@ -29128,6 +29115,7 @@ "version": "npm:vue-loader@16.8.3", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz", "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==", + "optional": true, "requires": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", @@ -29138,6 +29126,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "optional": true, "requires": { "color-convert": "^2.0.1" } @@ -29146,6 +29135,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "optional": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -29155,6 +29145,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, "requires": { "color-name": "~1.1.4" } @@ -29162,22 +29153,26 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "optional": true }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "optional": true }, "loader-utils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "optional": true, "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -29188,6 +29183,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "optional": true, "requires": { "has-flag": "^4.0.0" } diff --git a/website/client/package.json b/website/client/package.json index d9726f15c2..142b217ee8 100644 --- a/website/client/package.json +++ b/website/client/package.json @@ -33,6 +33,7 @@ "bootstrap-vue": "^2.21.2", "chai": "^4.3.6", "core-js": "^3.21.0", + "dompurify": "^2.3.8", "eslint": "^6.8.0", "eslint-config-habitrpg": "^6.2.0", "eslint-plugin-mocha": "^5.3.0", diff --git a/website/client/src/components/auth/registerLoginReset.vue b/website/client/src/components/auth/registerLoginReset.vue index eeecca89b1..7ecb8505b5 100644 --- a/website/client/src/components/auth/registerLoginReset.vue +++ b/website/client/src/components/auth/registerLoginReset.vue @@ -614,6 +614,7 @@ import axios from 'axios'; import hello from 'hellojs'; import debounce from 'lodash/debounce'; import isEmail from 'validator/lib/isEmail'; +import DOMPurify from 'dompurify'; import { buildAppleAuthUrl } from '../../libs/auth'; import { MINIMUM_PASSWORD_LENGTH } from '@/../../common/script/constants'; @@ -754,6 +755,12 @@ export default { } }); }, 500), + sanitizeRedirect (redirect) { + if (!redirect) return '/'; + let sanitizedString = DOMPurify.sanitize(redirect); + if (sanitizedString.slice(0, 1) !== '/') sanitizedString = `/${sanitizedString}`; + return sanitizedString; + }, async register () { // @TODO do not use alert if (!this.email) { @@ -785,19 +792,14 @@ export default { passwordConfirm: this.passwordConfirm, }); - let redirectTo; - - if (this.$route.query.redirectTo) { - redirectTo = this.$route.query.redirectTo; - } else { - redirectTo = '/'; - } + const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo); // @TODO do not reload entire page // problem is that app.vue created hook should be called again // after user is logged in / just signed up // ALSO it's the only way to make sure language data // is reloaded and correct for the logged in user + // Same situation in login and socialAuth functions window.location.href = redirectTo; }, async login () { @@ -807,19 +809,8 @@ export default { password: this.password, }); - let redirectTo; + const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo); - if (this.$route.query.redirectTo) { - redirectTo = this.$route.query.redirectTo; - } else { - redirectTo = '/'; - } - - // @TODO do not reload entire page - // problem is that app.vue created hook should be called again - // after user is logged in / just signed up - // ALSO it's the only way to make sure language data - // is reloaded and correct for the logged in user window.location.href = redirectTo; }, // @TODO: Abstract hello in to action or lib @@ -842,19 +833,8 @@ export default { auth, }); - let redirectTo; + const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo); - if (this.$route.query.redirectTo) { - redirectTo = this.$route.query.redirectTo; - } else { - redirectTo = '/'; - } - - // @TODO do not reload entire page - // problem is that app.vue created hook should be called again - // after user is logged in / just signed up - // ALSO it's the only way to make sure language data - // is reloaded and correct for the logged in user window.location.href = redirectTo; } },