mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-23 07:22:55 +02:00
Fix XSS in examples (#5688)
This commit is contained in:
@@ -41,9 +41,24 @@ const Element = props => {
|
||||
}
|
||||
}
|
||||
|
||||
const allowedSchemes = ['http:', 'https:']
|
||||
|
||||
const VideoElement = ({ attributes, children, element }) => {
|
||||
const editor = useSlateStatic()
|
||||
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 (
|
||||
<div {...attributes}>
|
||||
<div contentEditable={false}>
|
||||
@@ -54,7 +69,7 @@ const VideoElement = ({ attributes, children, element }) => {
|
||||
}}
|
||||
>
|
||||
<iframe
|
||||
src={`${url}?title=0&byline=0&portrait=0`}
|
||||
src={`${safeUrl}?title=0&byline=0&portrait=0`}
|
||||
frameBorder="0"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
|
@@ -242,12 +242,27 @@ const InlineChromiumBugfix = () => (
|
||||
</span>
|
||||
)
|
||||
|
||||
const allowedSchemes = ['http:', 'https:', 'mailto:', 'tel:']
|
||||
|
||||
const LinkComponent = ({ attributes, children, element }) => {
|
||||
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 (
|
||||
<a
|
||||
{...attributes}
|
||||
href={element.url}
|
||||
href={safeUrl}
|
||||
className={
|
||||
selected
|
||||
? css`
|
||||
|
@@ -160,15 +160,37 @@ const Element = props => {
|
||||
return <ol {...attributes}>{children}</ol>
|
||||
case 'link':
|
||||
return (
|
||||
<a href={element.url} {...attributes}>
|
||||
<SafeLink href={element.url} {...attributes}>
|
||||
{children}
|
||||
</a>
|
||||
</SafeLink>
|
||||
)
|
||||
case 'image':
|
||||
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 selected = useSelected()
|
||||
const focused = useFocused()
|
||||
|
Reference in New Issue
Block a user