From afcde542f9e991b4b671df191aa155e1ebee6006 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:51:17 +0200 Subject: [PATCH] fix: parse embeddable srcdoc urls strictly (#7884) --- packages/excalidraw/data/url.ts | 6 ++++- packages/excalidraw/element/embeddable.ts | 30 ++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/excalidraw/data/url.ts b/packages/excalidraw/data/url.ts index 2655c141d5..dae5760680 100644 --- a/packages/excalidraw/data/url.ts +++ b/packages/excalidraw/data/url.ts @@ -1,11 +1,15 @@ import { sanitizeUrl } from "@braintree/sanitize-url"; +export const sanitizeHTMLAttribute = (html: string) => { + return html.replace(/"/g, """); +}; + export const normalizeLink = (link: string) => { link = link.trim(); if (!link) { return link; } - return sanitizeUrl(link); + return sanitizeUrl(sanitizeHTMLAttribute(link)); }; export const isLocalLink = (link: string | null) => { diff --git a/packages/excalidraw/element/embeddable.ts b/packages/excalidraw/element/embeddable.ts index 40213aff83..8b55a54419 100644 --- a/packages/excalidraw/element/embeddable.ts +++ b/packages/excalidraw/element/embeddable.ts @@ -11,6 +11,7 @@ import { ExcalidrawIframeLikeElement, IframeData, } from "./types"; +import { sanitizeHTMLAttribute } from "../data/url"; const embeddedLinkCache = new Map(); @@ -21,12 +22,13 @@ const RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}\.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/; const RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/; -const RE_GH_GIST = /^https:\/\/gist\.github\.com/; +const RE_GH_GIST = /^https:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)/; const RE_GH_GIST_EMBED = - /https?:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)\.js["']/i; + /^ twitter embeds -const RE_TWITTER = /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com/; +const RE_TWITTER = + /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com\/[^/]+\/status\/(\d+)/; const RE_TWITTER_EMBED = /^ createSrcDoc( - ` `, + ` `, ), intrinsicSize: { w: 480, h: 480 }, sandbox: { allowSameOrigin: true }, @@ -167,11 +175,15 @@ export const getEmbedLink = ( } if (RE_GH_GIST.test(link)) { + const [, user, gistId] = link.match(RE_GH_GIST)!; + const safeURL = sanitizeHTMLAttribute( + `https://gist.github.com/${user}/${gistId}`, + ); const ret: IframeData = { type: "document", srcdoc: () => createSrcDoc(` - +