From 2879c9d85269539043eb23b15afa49fccce95c6a Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:57:43 +0200 Subject: [PATCH] fix: Gist embed allowing unsafe html (#7883) --- src/components/App.tsx | 6 +++- src/element/embeddable.ts | 71 ++++++++++++++------------------------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 42080e831..f40d03828 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -946,7 +946,11 @@ class App extends React.Component { title="Excalidraw Embedded Content" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen={true} - sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads" + sandbox={`${ + embedLink?.sandbox?.allowSameOrigin + ? "allow-same-origin" + : "" + } allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads`} /> )} diff --git a/src/element/embeddable.ts b/src/element/embeddable.ts index e03ea7a61..81de4e90c 100644 --- a/src/element/embeddable.ts +++ b/src/element/embeddable.ts @@ -18,6 +18,7 @@ type EmbeddedLink = | ({ aspectRatio: { w: number; h: number }; warning?: string; + sandbox?: { allowSameOrigin?: boolean }; } & ( | { type: "video" | "generic"; link: string } | { type: "document"; srcdoc: (theme: Theme) => string } @@ -30,20 +31,20 @@ const RE_YOUTUBE = /^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/; const RE_VIMEO = - /^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/; + /^(?: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_EMBED = - /^ twitter embeds -const RE_TWITTER = /(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?twitter.com/; +const RE_TWITTER = /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com/; const RE_TWITTER_EMBED = - /^$/i; @@ -143,46 +144,27 @@ export const getEmbedLink = (link: string | null | undefined): EmbeddedLink => { } if (RE_TWITTER.test(link)) { - let ret: EmbeddedLink; - // assume embed code - if (/
srcDoc, - aspectRatio: { w: 480, h: 480 }, - }; - // assume regular tweet url - } else { - ret = { - type: "document", - srcdoc: (theme: string) => - createSrcDoc( - ` `, - ), - aspectRatio: { w: 480, h: 480 }, - }; - } + // the embed srcdoc still supports twitter.com domain only + link = link.replace(/\bx.com\b/, "twitter.com"); + + const ret: EmbeddedLink = { + type: "document", + srcdoc: (theme: string) => + createSrcDoc( + ` `, + ), + aspectRatio: { w: 480, h: 480 }, + sandbox: { allowSameOrigin: true }, + }; embeddedLinkCache.set(originalLink, ret); return ret; } if (RE_GH_GIST.test(link)) { - let ret: EmbeddedLink; - // assume embed code - if (/ `), - aspectRatio: { w: 550, h: 720 }, - }; - } + aspectRatio: { w: 550, h: 720 }, + }; embeddedLinkCache.set(link, ret); return ret; } @@ -310,8 +291,8 @@ export const extractSrc = (htmlString: string): string => { } const gistMatch = htmlString.match(RE_GH_GIST_EMBED); - if (gistMatch && gistMatch.length === 2) { - return gistMatch[1]; + if (gistMatch && gistMatch.length === 3) { + return `https://gist.github.com/${gistMatch[1]}/${gistMatch[2]}`; } if (RE_GIPHY.test(htmlString)) {