Skip to content

Commit bc620da

Browse files
authored
fix: XSS injection with Querybook RichTextEditor (#1412)
1 parent 34cb6d3 commit bc620da

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "querybook",
3-
"version": "3.31.0",
3+
"version": "3.31.1",
44
"description": "A Big Data Webapp",
55
"private": true,
66
"scripts": {

querybook/webapp/lib/richtext/index.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as DraftJs from 'draft-js';
22
import type { Stack } from 'immutable';
3-
import React from 'react';
3+
import React, { useMemo } from 'react';
44

55
import { Link } from 'ui/Link/Link';
66

@@ -10,9 +10,25 @@ interface IUrlLinkProps {
1010
}
1111

1212
const UrlLink: React.FunctionComponent<IUrlLinkProps> = (props) => {
13-
const { url } = props.contentState.getEntity(props.entityKey).getData();
13+
const { url }: { url: string } = props.contentState
14+
.getEntity(props.entityKey)
15+
.getData();
16+
const sanitizedUrl = useMemo(() => {
17+
// sanitize URL to prevent XSS
18+
try {
19+
const urlObj = new URL(url);
20+
if (['http:', 'https:'].includes(urlObj.protocol)) {
21+
return urlObj.href;
22+
} else {
23+
return undefined;
24+
}
25+
} catch (error) {
26+
return undefined;
27+
}
28+
}, [url]);
29+
1430
return (
15-
<Link to={url} newTab>
31+
<Link to={sanitizedUrl ?? 'about:blank'} newTab>
1632
{props.children}
1733
</Link>
1834
);

0 commit comments

Comments
 (0)