From 232d118bd4c8f70661f3a74b75424dae43dd0f2f Mon Sep 17 00:00:00 2001 From: "Pablo H. Paladino" Date: Wed, 24 Aug 2022 15:56:47 -0300 Subject: [PATCH] sanitize location attributes in store --- packages/core/src/helpers/stripHTML.js | 24 ++++++++++++++++++++++++ packages/core/src/server.jsx | 16 ++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 packages/core/src/helpers/stripHTML.js diff --git a/packages/core/src/helpers/stripHTML.js b/packages/core/src/helpers/stripHTML.js new file mode 100644 index 000000000..b1e915b73 --- /dev/null +++ b/packages/core/src/helpers/stripHTML.js @@ -0,0 +1,24 @@ +// Internal list of HTML entities for escaping. +const entities = { + "&": "&", + "<": "<", + ">": ">", + """: "\"", + "'": "'", + "`": "`", + " ": "" +}; + +const source = `(?:${ Object.keys(entities).join("|") })`; +const testRegexp = RegExp(source); +const replaceRegexp = RegExp(source, "g"); + +/** +* Converts html tags to spaces, then removes redundant spaces +*/ +function stripHTML(n) { + const s = String(n).replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim(); + return testRegexp.test(s) ? s.replace(replaceRegexp, match => entities[match]) : s; +} + +module.exports = stripHTML; diff --git a/packages/core/src/server.jsx b/packages/core/src/server.jsx index f987cf12b..0f8cc3bc3 100644 --- a/packages/core/src/server.jsx +++ b/packages/core/src/server.jsx @@ -13,6 +13,7 @@ import {initialState as appInitialState} from "$app/store"; import preRenderMiddleware from "./middlewares/preRenderMiddleware"; import pretty from "pretty"; import maybeRedirect from "./helpers/maybeRedirect"; +import stripHTML from "./helpers/stripHTML"; import {servicesAvailable, servicesBody, servicesScript, servicesHeadTags} from "./helpers/services"; import yn from "yn"; @@ -32,6 +33,13 @@ const baseTag = process.env.CANON_BASE_URL === undefined ? "" : ` `; + +const getCleanedParams = queryParams => { + return Object.keys(queryParams).reduce((params, paramKey) => { + params[stripHTML(paramKey)] = stripHTML(queryParams[paramKey]); + return params; + }, {}) +} /** Returns the default server logic for rendering a page. */ @@ -46,13 +54,13 @@ export default function(defaultStore = appInitialState, headerConfig, reduxMiddl basename, host: req.headers.host, hostname: req.headers.host.split(":")[0], - href: `${req.protocol}://${req.headers.host}${req.url}`, + href: `${req.protocol}://${stripHTML(`${req.headers.host}${req.url}`)}`, origin: `${req.protocol}://${req.headers.host}`, - pathname: req.url.split("?")[0], + pathname: stripHTML(req.url.split("?")[0]), port: req.headers.host.includes(":") ? req.headers.host.split(":")[1] : "80", protocol: `${req.protocol}:`, - query: req.query, - search: req.url.includes("?") ? `?${req.url.split("?")[1]}` : "" + query: getCleanedParams(req.query), + search: req.url.includes("?") ? `?${stripHTML(req.url.split("?")[1])}` : "" }; const location = req.url.replace(BASE_URL, "");