Skip to content

Commit d9efa1b

Browse files
neuracrdylhunn
authored andcommitted
feat(core): change the URL sanitization to only block javascript: URLs (#49659)
In modern browsers, the 'javascript:' URL scheme is the only scheme that can execute JavaScript when passed in a navigation URL context (e.g. `a.href` value). Validate URL shemes to only contain characters allowed in the URL specification ([a-zA-Z-+.]), and that are not javascript (case insensitive). This is not a breaking change. The URL sanitization is loosen. PR Close #49659
1 parent c26e4be commit d9efa1b

File tree

2 files changed

+8
-7
lines changed

2 files changed

+8
-7
lines changed

packages/core/src/sanitization/url_sanitizer.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
import {XSS_SECURITY_URL} from '../error_details_base_url';
1010

1111
/**
12-
* A pattern that recognizes a commonly useful subset of URLs that are safe.
12+
* A pattern that recognizes URLs that are safe wrt. XSS in URL navigation
13+
* contexts.
1314
*
1415
* This regular expression matches a subset of URLs that will not cause script
1516
* execution if used in URL context within a HTML document. Specifically, this
16-
* regular expression matches if (comment from here on and regex copied from
17-
* Soy's EscapingConventions):
18-
* (1) Either an allowed protocol (http, https, mailto or ftp).
17+
* regular expression matches if:
18+
* (1) Either a protocol that is not javascript:, and that has valid characters
19+
* (alphanumeric or [+-.]).
1920
* (2) or no protocol. A protocol must be followed by a colon. The below
2021
* allows that by allowing colons only after one of the characters [/?#].
2122
* A colon after a hash (#) must be in the fragment.
@@ -34,8 +35,7 @@ import {XSS_SECURITY_URL} from '../error_details_base_url';
3435
*
3536
* This regular expression was taken from the Closure sanitization library.
3637
*/
37-
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|data|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
38-
38+
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
3939
export function _sanitizeUrl(url: string): string {
4040
url = String(url);
4141
if (url.match(SAFE_URL_PATTERN)) return url;

packages/core/test/sanitization/url_sanitizer_spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {_sanitizeUrl} from '../../src/sanitization/url_sanitizer';
4747
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
4848
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
4949
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
50+
'unknown-scheme:abc',
5051
];
5152
for (const url of validUrls) {
5253
it(`valid ${url}`, () => expect(_sanitizeUrl(url)).toEqual(url));
@@ -57,7 +58,7 @@ import {_sanitizeUrl} from '../../src/sanitization/url_sanitizer';
5758
const invalidUrls = [
5859
'javascript:evil()',
5960
'JavaScript:abc',
60-
'evilNewProtocol:abc',
61+
' javascript:abc',
6162
' \n Java\n Script:abc',
6263
'javascript:',
6364
'&#106avascript:',

0 commit comments

Comments
 (0)