fix(extension-youtube) XSS risk with src tag

Fixes risks outline in #4600 by verifying that any src urls are valid
youtube URLs before rendering as HTML. My thoughts are that this attack
vector would be difficult to use because the attacker would have to have
a way to manipualte the TipTap payload in a manner that bypasses the
youtube extension's `setYoutubeVideo` command, which already checks for
valid URLs.
This commit is contained in:
Cameron Hessler 2023-11-06 00:57:56 -06:00 committed by Jan Thurau
parent acbf47e5a7
commit 04a11355a7
2 changed files with 63 additions and 0 deletions

View File

@ -52,6 +52,10 @@ export const getEmbedUrlFromYoutubeUrl = (options: GetEmbedUrlOptions) => {
startAt,
} = options
if (!isValidYoutubeUrl(url)) {
return null
}
// if is already an embed url, return it
if (url.includes('/embed/')) {
return url

View File

@ -0,0 +1,59 @@
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import Youtube from '@tiptap/extension-youtube'
/**
* Most youtube tests should actually exist in the demo/ app folder
*/
describe('extension-youtube', () => {
const editorElClass = 'tiptap'
let editor: Editor | null = null
const createEditorEl = () => {
const editorEl = document.createElement('div')
editorEl.classList.add(editorElClass)
document.body.appendChild(editorEl)
return editorEl
}
const getEditorEl = () => document.querySelector(`.${editorElClass}`)
const invalidUrls = [
// We have to disable the eslint rule here because we're trying to purposely test eval urls
// eslint-disable-next-line no-script-url
'javascript:alert(window.origin)//embed/',
'https://youtube.google.com/embed/fdsafsdf',
]
invalidUrls.forEach(url => {
it(`does not output html for javascript schema or non-youtube links for url ${url}`, () => {
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
Youtube,
],
content: {
type: 'doc',
content: [
{
type: 'youtube',
attrs: {
src: url,
},
},
],
},
})
expect(editor.getHTML()).to.not.include(url)
editor?.destroy()
getEditorEl()?.remove()
})
})
})