21026: <msg here> Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox@curii.com>
authorLisa Knox <lisaknox83@gmail.com>
Thu, 12 Oct 2023 19:36:12 +0000 (15:36 -0400)
committerLisa Knox <lisaknox83@gmail.com>
Thu, 12 Oct 2023 19:36:12 +0000 (15:36 -0400)
package.json
src/common/html-sanitize.ts [new file with mode: 0644]
src/views-components/details-panel/project-details.tsx
yarn.lock

index 63cf8a11a5e30cac4c0ae968fed90fec24b0bce1..35c960c4186d132d2eb477c4ee4495204f142ec4 100644 (file)
@@ -10,6 +10,7 @@
     "@material-ui/core": "3.9.3",
     "@material-ui/icons": "3.0.1",
     "@types/debounce": "3.0.0",
+    "@types/dompurify": "^3.0.3",
     "@types/file-saver": "2.0.0",
     "@types/js-yaml": "3.11.2",
     "@types/jssha": "0.0.29",
@@ -31,6 +32,7 @@
     "cwlts": "1.15.29",
     "date-fns": "^2.28.0",
     "debounce": "1.2.0",
+    "dompurify": "^3.0.6",
     "elliptic": "6.5.4",
     "file-saver": "2.0.1",
     "fstream": "1.0.12",
diff --git a/src/common/html-sanitize.ts b/src/common/html-sanitize.ts
new file mode 100644 (file)
index 0000000..9c1ac55
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import DOMPurify from 'dompurify';
+
+type TDomPurifyConfig = {
+    ALLOWED_TAGS: string[];
+    ALLOWED_ATTR: string[];
+};
+
+const domPurifyConfig: TDomPurifyConfig = {
+    ALLOWED_TAGS: [
+        'a',
+        'b',
+        'blockquote',
+        'br',
+        'code',
+        'del',
+        'dd',
+        'dl',
+        'dt',
+        'em',
+        'h1',
+        'h2',
+        'h3',
+        'h4',
+        'h5',
+        'h6',
+        'hr',
+        'i',
+        'img',
+        'kbd',
+        'li',
+        'ol',
+        'p',
+        'pre',
+        's',
+        'del',
+        'strong',
+        'sub',
+        'sup',
+        'ul',
+    ],
+    ALLOWED_ATTR: ['src', 'width', 'height', 'href', 'alt', 'title'],
+};
+
+export const sanitizeHTML = (dirtyInput: string): string => {
+    console.log('dirty ->',dirtyInput);
+    const clean = DOMPurify.sanitize(dirtyInput, domPurifyConfig);
+    console.log('clean =>',clean);
+    return clean;
+};
index 7dc6709da591a84a7ecd813582aa509733008c0a..ecc8c3285847a73fd4017158e4017318fda03bf8 100644 (file)
@@ -22,6 +22,7 @@ import { openProjectUpdateDialog, ProjectUpdateFormDialogData } from 'store/proj
 import { RootState } from 'store/store';
 import { ResourcesState } from 'store/resources/resources';
 import { resourceIsFrozen } from 'common/frozen-resources';
+import { sanitizeHTML } from 'common/html-sanitize';
 
 export class ProjectDetails extends DetailsData<ProjectResource> {
     getIcon(className?: string) {
@@ -102,7 +103,7 @@ const ProjectDetailsComponent = connect(mapStateToProps, mapDispatchToProps)(
                 {project.description ?
                     <RichTextEditorLink
                         title={`Description of ${project.name}`}
-                        content={project.description}
+                        content={sanitizeHTML(project.description)}
                         label='Show full description' />
                     : '---'
                 }
index 54b1883af9c78132d6a9ca1b6463d47eaf2ae52b..f9dfa6a9546b954ed10657180b72387ff2e8c508 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
@@ -2508,6 +2508,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/dompurify@npm:^3.0.3":
+  version: 3.0.3
+  resolution: "@types/dompurify@npm:3.0.3"
+  dependencies:
+    "@types/trusted-types": "*"
+  checksum: ff629277db4d19d836b0d878e93efb27d876d1073db81507c39d44d509b30ee3bcdc9e951dbbf9574b1fc6c52e1eaa95abf4279fa45aca281868717f8a7298da
+  languageName: node
+  linkType: hard
+
 "@types/enzyme-adapter-react-16@npm:1.0.3":
   version: 1.0.3
   resolution: "@types/enzyme-adapter-react-16@npm:1.0.3"
@@ -2918,6 +2927,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/trusted-types@npm:*":
+  version: 2.0.4
+  resolution: "@types/trusted-types@npm:2.0.4"
+  checksum: 5256c4576cd1c90d33ddd9cc9cbd4f202b39c98cbe8b7f74963298f9eb2159c285ea5c25a6181b4c594d8d75641765bff85d72c2d251ad076e6529ce0eeedd1c
+  languageName: node
+  linkType: hard
+
 "@types/uuid@npm:3.4.4":
   version: 3.4.4
   resolution: "@types/uuid@npm:3.4.4"
@@ -3793,6 +3809,7 @@ __metadata:
     "@sinonjs/fake-timers": ^10.3.0
     "@types/classnames": 2.2.6
     "@types/debounce": 3.0.0
+    "@types/dompurify": ^3.0.3
     "@types/enzyme": 3.1.14
     "@types/enzyme-adapter-react-16": 1.0.3
     "@types/file-saver": 2.0.0
@@ -3830,6 +3847,7 @@ __metadata:
     cypress: 6.3.0
     date-fns: ^2.28.0
     debounce: 1.2.0
+    dompurify: ^3.0.6
     elliptic: 6.5.4
     enzyme: 3.11.0
     enzyme-adapter-react-16: 1.15.6
@@ -6887,6 +6905,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dompurify@npm:^3.0.6":
+  version: 3.0.6
+  resolution: "dompurify@npm:3.0.6"
+  checksum: e5c6cdc5fe972a9d0859d939f1d86320de275be00bbef7bd5591c80b1e538935f6ce236624459a1b0c84ecd7c6a1e248684aa4637512659fccc0ce7c353828a6
+  languageName: node
+  linkType: hard
+
 "domutils@npm:^1.7.0":
   version: 1.7.0
   resolution: "domutils@npm:1.7.0"