1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-23 23:42:56 +02:00

Fix XSS in examples (#5688)

This commit is contained in:
Joe Anderson
2024-08-01 15:41:44 +01:00
committed by GitHub
parent 6548197540
commit a6910b70a0
3 changed files with 56 additions and 4 deletions

View File

@@ -41,9 +41,24 @@ const Element = props => {
} }
} }
const allowedSchemes = ['http:', 'https:']
const VideoElement = ({ attributes, children, element }) => { const VideoElement = ({ attributes, children, element }) => {
const editor = useSlateStatic() const editor = useSlateStatic()
const { url } = element const { url } = element
const safeUrl = useMemo(() => {
let parsedUrl: URL = null
try {
parsedUrl = new URL(url)
// eslint-disable-next-line no-empty
} catch {}
if (parsedUrl && allowedSchemes.includes(parsedUrl.protocol)) {
return parsedUrl.href
}
return 'about:blank'
}, [url])
return ( return (
<div {...attributes}> <div {...attributes}>
<div contentEditable={false}> <div contentEditable={false}>
@@ -54,7 +69,7 @@ const VideoElement = ({ attributes, children, element }) => {
}} }}
> >
<iframe <iframe
src={`${url}?title=0&byline=0&portrait=0`} src={`${safeUrl}?title=0&byline=0&portrait=0`}
frameBorder="0" frameBorder="0"
style={{ style={{
position: 'absolute', position: 'absolute',

View File

@@ -242,12 +242,27 @@ const InlineChromiumBugfix = () => (
</span> </span>
) )
const allowedSchemes = ['http:', 'https:', 'mailto:', 'tel:']
const LinkComponent = ({ attributes, children, element }) => { const LinkComponent = ({ attributes, children, element }) => {
const selected = useSelected() const selected = useSelected()
const safeUrl = useMemo(() => {
let parsedUrl: URL = null
try {
parsedUrl = new URL(element.url)
// eslint-disable-next-line no-empty
} catch {}
if (parsedUrl && allowedSchemes.includes(parsedUrl.protocol)) {
return parsedUrl.href
}
return 'about:blank'
}, [element.url])
return ( return (
<a <a
{...attributes} {...attributes}
href={element.url} href={safeUrl}
className={ className={
selected selected
? css` ? css`

View File

@@ -160,15 +160,37 @@ const Element = props => {
return <ol {...attributes}>{children}</ol> return <ol {...attributes}>{children}</ol>
case 'link': case 'link':
return ( return (
<a href={element.url} {...attributes}> <SafeLink href={element.url} {...attributes}>
{children} {children}
</a> </SafeLink>
) )
case 'image': case 'image':
return <ImageElement {...props} /> return <ImageElement {...props} />
} }
} }
const allowedSchemes = ['http:', 'https:', 'mailto:', 'tel:']
const SafeLink = ({ attributes, children, href }) => {
const safeHref = useMemo(() => {
let parsedUrl: URL = null
try {
parsedUrl = new URL(href)
// eslint-disable-next-line no-empty
} catch {}
if (parsedUrl && allowedSchemes.includes(parsedUrl.protocol)) {
return parsedUrl.href
}
return 'about:blank'
}, [href])
return (
<a href={safeHref} {...attributes}>
{children}
</a>
)
}
const ImageElement = ({ attributes, children, element }) => { const ImageElement = ({ attributes, children, element }) => {
const selected = useSelected() const selected = useSelected()
const focused = useFocused() const focused = useFocused()