Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 3e4175f

Browse files
committed
Add isUrlPermitted function
1 parent 1a283f9 commit 3e4175f

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

src/HtmlUtils.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Copyright 2015, 2016 OpenMarket Ltd
3-
Copyright 2017 New Vector Ltd
3+
Copyright 2017, 2018 New Vector Ltd
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import escape from 'lodash/escape';
2525
import emojione from 'emojione';
2626
import classNames from 'classnames';
2727
import MatrixClientPeg from './MatrixClientPeg';
28+
import url from 'url';
2829

2930
emojione.imagePathSVG = 'emojione/svg/';
3031
// Store PNG path for displaying many flags at once (for increased performance over SVG)
@@ -44,6 +45,8 @@ const SYMBOL_PATTERN = /([\u2100-\u2bff])/;
4445
const EMOJI_REGEX = new RegExp(emojione.unicodeRegexp+"+", "gi");
4546
const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/;
4647

48+
const PERMITTED_URL_SCHEMES = ['http', 'https', 'ftp', 'mailto', 'magnet'];
49+
4750
/*
4851
* Return true if the given string contains emoji
4952
* Uses a much, much simpler regex than emojione's so will give false
@@ -152,6 +155,25 @@ export function sanitizedHtmlNode(insaneHtml) {
152155
return <div dangerouslySetInnerHTML={{ __html: saneHtml }} dir="auto" />;
153156
}
154157

158+
/**
159+
* Tests if a URL from an untrusted source may be safely put into the DOM
160+
* The biggest threat here is javascript: URIs.
161+
* Note that the HTML sanitiser library has its own internal logic for
162+
* doing this, to which we pass the same list of schemes. This is used in
163+
* other places we need to sanitise URLs.
164+
* @return true if permitted, otherwise false
165+
*/
166+
export function isUrlPermitted(inputUrl) {
167+
try {
168+
const parsed = url.parse(inputUrl);
169+
if (!parsed.protocol) return false;
170+
// URL parser protocol includes the trailing colon
171+
return PERMITTED_URL_SCHEMES.includes(parsed.protocol.slice(0, -1));
172+
} catch (e) {
173+
return false;
174+
}
175+
}
176+
155177
const sanitizeHtmlParams = {
156178
allowedTags: [
157179
'font', // custom to matrix for IRC-style font coloring
@@ -172,7 +194,7 @@ const sanitizeHtmlParams = {
172194
// Lots of these won't come up by default because we don't allow them
173195
selfClosing: ['img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta'],
174196
// URL schemes we permit
175-
allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'magnet'],
197+
allowedSchemes: PERMITTED_URL_SCHEMES,
176198

177199
allowProtocolRelative: false,
178200

0 commit comments

Comments
 (0)