From 2613420cd1861493130fb9e961c9da4bca2d61d1 Mon Sep 17 00:00:00 2001
From: Hayden <64056131+hay-kot@users.noreply.github.com>
Date: Sun, 24 Apr 2022 13:00:04 -0800
Subject: [PATCH] security: fix unsafe html inputs (#1173)
* use DomPurify to sanatize ingredient html
* fix list-item render for markdown
* address volar linter issue
---
.../Domain/Recipe/RecipeInstructions.vue | 17 ++++++++++++++---
.../recipes/use-recipe-ingredients.ts | 13 +++++++++++--
frontend/package.json | 3 ++-
frontend/tsconfig.json | 1 +
frontend/yarn.lock | 5 +++++
5 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/frontend/components/Domain/Recipe/RecipeInstructions.vue b/frontend/components/Domain/Recipe/RecipeInstructions.vue
index 9be76503ab5d..37fd159d56f4 100644
--- a/frontend/components/Domain/Recipe/RecipeInstructions.vue
+++ b/frontend/components/Domain/Recipe/RecipeInstructions.vue
@@ -173,8 +173,8 @@
-
-
+
+
@@ -506,8 +506,19 @@ export default defineComponent({
});
-
diff --git a/frontend/composables/recipes/use-recipe-ingredients.ts b/frontend/composables/recipes/use-recipe-ingredients.ts
index 7f154504205c..0829783e413a 100644
--- a/frontend/composables/recipes/use-recipe-ingredients.ts
+++ b/frontend/composables/recipes/use-recipe-ingredients.ts
@@ -1,8 +1,16 @@
+// @ts-ignore DOMPurify has no types
+import DOMPurify from "dompurify";
import { useFraction } from "./use-fraction";
import { RecipeIngredient } from "~/types/api-types/recipe";
-
const { frac } = useFraction();
+function sanitizeIngredientHTML(rawHtml: string) {
+ return DOMPurify.sanitize(rawHtml, {
+ "USE_PROFILES": {html: true},
+ "ALLOWED_TAGS": ["b", "q", "i", "strong", "sup"]
+ }) as string
+}
+
export function parseIngredientText(ingredient: RecipeIngredient, disableAmount: boolean, scale = 1): string {
if (disableAmount) {
return ingredient.note || "";
@@ -26,5 +34,6 @@ export function parseIngredientText(ingredient: RecipeIngredient, disableAmount:
}
}
- return `${returnQty} ${unit?.name || " "} ${food?.name || " "} ${note || " "}`.replace(/ {2,}/g, " ");
+ const text = `${returnQty} ${unit?.name || " "} ${food?.name || " "} ${note || " "}`.replace(/ {2,}/g, " ");
+ return sanitizeIngredientHTML(text);
}
diff --git a/frontend/package.json b/frontend/package.json
index d0e6677e7946..65c00fcf5692 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -25,6 +25,7 @@
"@vueuse/core": "^6.8.0",
"core-js": "^3.15.1",
"date-fns": "^2.23.0",
+ "dompurify": "^2.3.6",
"fuse.js": "^6.5.3",
"nuxt": "^2.15.8",
"v-jsoneditor": "^1.4.5",
@@ -55,4 +56,4 @@
"resolutions": {
"vite": "2.3.8"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index 8c44455991ae..a57417498b74 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "jsx": "preserve",
"target": "ES2018",
"module": "ESNext",
"moduleResolution": "Node",
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 3da7456c9218..aac6d13df146 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -4898,6 +4898,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0:
dependencies:
domelementtype "^2.2.0"
+dompurify@^2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
+ integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
+
domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"