Browse Source

fix: better support for target="_blank" links in sanitization

Sv443 7 months ago
parent
commit
117de9503a
1 changed files with 20 additions and 5 deletions
  1. 20 5
      src/utils/dom.ts

+ 20 - 5
src/utils/dom.ts

@@ -239,10 +239,24 @@ export function copyToClipboard(text: Stringifiable) {
 
 let ttPolicy: TTPolicy | undefined;
 
-DOMPurify.addHook("afterSanitizeAttributes", function (node) {
-  if("target" in node) {
-    node.setAttribute("target", "_blank");
-    node.setAttribute("rel", "noopener noreferrer");
+// workaround for supporting `target="_blank"` links without compromising security:
+const tempTargetAttrName = `data-tmp-target-${randomId(6, 36)}`;
+
+DOMPurify.addHook("beforeSanitizeAttributes", (node) => {
+  if(node.tagName === "A") {
+    if(!node.hasAttribute("target"))
+      node.setAttribute("target", "_self");
+    if(node.hasAttribute("target"))
+      node.setAttribute(tempTargetAttrName, node.getAttribute("target")!);
+  }
+});
+
+DOMPurify.addHook("afterSanitizeAttributes", (node) => {
+  if(node.tagName === "A" && node.hasAttribute(tempTargetAttrName)) {
+    node.setAttribute("target", node.getAttribute(tempTargetAttrName)!);
+    node.removeAttribute(tempTargetAttrName);
+    if(node.getAttribute("target") === "_blank")
+      node.setAttribute("rel", "noopener noreferrer");
   }
 });
 
@@ -256,5 +270,6 @@ export function setInnerHtml(element: HTMLElement, html: string) {
     });
   }
 
-  element.innerHTML = ttPolicy?.createHTML(html) ?? DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: false });
+  element.innerHTML = ttPolicy?.createHTML(html)
+    ?? DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: false });
 }