Skip to content

Commit fc9b2d6

Browse files
committed
Revert "fix(core): block dangerous data: and vbscript: URLs in URL sanitizer"
This reverts commit e96936a.
1 parent bab72b9 commit fc9b2d6

3 files changed

Lines changed: 6 additions & 44 deletions

File tree

‎packages/core/src/sanitization/html_sanitizer.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,7 @@ class SanitizingHtmlSerializer {
195195
continue;
196196
}
197197
let value = elAttr!.value;
198-
// Note: data: URIs with dangerous subtypes (e.g. data:text/html) are now blocked
199-
// by _sanitizeUrl, while safe media subtypes (data:image/*, data:video/*, data:audio/*)
200-
// are still allowed.
198+
// TODO(martinprobst): Special case image URIs for data:image/...
201199
if (URI_ATTRS[lower]) value = _sanitizeUrl(value);
202200
this.buf.push(' ', attrName, '="', encodeEntities(value), '"');
203201
}

‎packages/core/src/sanitization/url_sanitizer.ts‎

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ import {XSS_SECURITY_URL} from '../error_details_base_url';
1515
* This regular expression matches a subset of URLs that will not cause script
1616
* execution if used in URL context within a HTML document. Specifically, this
1717
* regular expression matches if:
18-
* (1) Either a protocol that is not javascript: or vbscript:, and that has
19-
* valid characters (alphanumeric or [+-.]).
20-
* For data: URIs, only safe media subtypes (image/*, video/*, audio/*)
21-
* are allowed. Other data: subtypes (e.g. data:text/html) are blocked
22-
* as they can lead to script execution in some environments.
18+
* (1) Either a protocol that is not javascript:, and that has valid characters
19+
* (alphanumeric or [+-.]).
2320
* (2) or no protocol. A protocol must be followed by a colon. The below
2421
* allows that by allowing colons only after one of the characters [/?#].
2522
* A colon after a hash (#) must be in the fragment.
@@ -36,16 +33,9 @@ import {XSS_SECURITY_URL} from '../error_details_base_url';
3633
* that. More importantly, it disallows masking of a colon,
3734
* e.g. "javascript:...".
3835
*
39-
* This regular expression was originally taken from the Closure sanitization
40-
* library and extended to also block vbscript: and dangerous data: subtypes.
41-
*
42-
* Note: data:image/svg+xml is allowed because SVG loaded via <img src> is
43-
* sandboxed by browsers (scripts do not execute). For <a href> contexts,
44-
* modern browsers (Chrome 60+, Firefox 59+) block top-level navigation to
45-
* data: URLs entirely, providing an additional layer of defense.
36+
* This regular expression was taken from the Closure sanitization library.
4637
*/
47-
const SAFE_URL_PATTERN =
48-
/^(?!javascript:)(?!vbscript:)(?!data:(?!image\/|video\/|audio\/))(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
38+
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
4939
export function _sanitizeUrl(url: string): string {
5040
url = String(url);
5141
if (url.match(SAFE_URL_PATTERN)) return url;

‎packages/core/test/sanitization/url_sanitizer_spec.ts‎

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ describe('URL sanitizer', () => {
4646
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
4747
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
4848
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
49-
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==',
50-
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
5149
'unknown-scheme:abc',
5250
];
5351
for (const url of validUrls) {
@@ -70,31 +68,7 @@ describe('URL sanitizer', () => {
7068
'jav\u0000ascript:alert();',
7169
];
7270
for (const url of invalidUrls) {
73-
it(`invalid ${url}`, () => expect(_sanitizeUrl(url)).toMatch(/^unsafe:/));
74-
}
75-
});
76-
77-
describe('vbscript URLs', () => {
78-
const vbscriptUrls = ['vbscript:MsgBox("XSS")', 'VBScript:alert()', 'VBSCRIPT:MsgBox("XSS")'];
79-
for (const url of vbscriptUrls) {
80-
it(`blocks ${url}`, () => expect(_sanitizeUrl(url)).toMatch(/^unsafe:/));
81-
}
82-
});
83-
84-
describe('dangerous data: URLs', () => {
85-
const dangerousDataUrls = [
86-
'data:text/html,<script>alert(1)</script>',
87-
'data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==',
88-
'data:application/xhtml+xml,<script>alert(1)</script>',
89-
'data:text/xml,<script>alert(1)</script>',
90-
'DATA:text/html,<script>alert(1)</script>',
91-
'data:,<script>alert(1)</script>',
92-
'data:application/javascript,alert(1)',
93-
'data:text/plain,hello',
94-
'data:application/pdf;base64,abc',
95-
];
96-
for (const url of dangerousDataUrls) {
97-
it(`blocks ${url}`, () => expect(_sanitizeUrl(url)).toMatch(/^unsafe:/));
71+
it(`valid ${url}`, () => expect(_sanitizeUrl(url)).toMatch(/^unsafe:/));
9872
}
9973
});
10074
});

0 commit comments

Comments
 (0)