mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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
This commit is contained in:
committed by
Dylan Hunn
parent
f0978ad0ec
commit
b35fa73968
@@ -9,13 +9,14 @@
|
||||
import {XSS_SECURITY_URL} from '../error_details_base_url';
|
||||
|
||||
/**
|
||||
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
||||
* A pattern that recognizes URLs that are safe wrt. XSS in URL navigation
|
||||
* contexts.
|
||||
*
|
||||
* This regular expression matches a subset of URLs that will not cause script
|
||||
* execution if used in URL context within a HTML document. Specifically, this
|
||||
* regular expression matches if (comment from here on and regex copied from
|
||||
* Soy's EscapingConventions):
|
||||
* (1) Either an allowed protocol (http, https, mailto or ftp).
|
||||
* regular expression matches if:
|
||||
* (1) Either a protocol that is not javascript:, and that has valid characters
|
||||
* (alphanumeric or [+-.]).
|
||||
* (2) or no protocol. A protocol must be followed by a colon. The below
|
||||
* allows that by allowing colons only after one of the characters [/?#].
|
||||
* A colon after a hash (#) must be in the fragment.
|
||||
@@ -34,8 +35,7 @@ import {XSS_SECURITY_URL} from '../error_details_base_url';
|
||||
*
|
||||
* This regular expression was taken from the Closure sanitization library.
|
||||
*/
|
||||
const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|data|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
|
||||
|
||||
const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\/?#]*(?:[\/?#]|$))/i;
|
||||
export function _sanitizeUrl(url: string): string {
|
||||
url = String(url);
|
||||
if (url.match(SAFE_URL_PATTERN)) return url;
|
||||
|
||||
@@ -47,6 +47,7 @@ import {_sanitizeUrl} from '../../src/sanitization/url_sanitizer';
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/', // Truncated.
|
||||
'data:video/webm;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
||||
'data:audio/opus;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/',
|
||||
'unknown-scheme:abc',
|
||||
];
|
||||
for (const url of validUrls) {
|
||||
it(`valid ${url}`, () => expect(_sanitizeUrl(url)).toEqual(url));
|
||||
@@ -57,7 +58,7 @@ import {_sanitizeUrl} from '../../src/sanitization/url_sanitizer';
|
||||
const invalidUrls = [
|
||||
'javascript:evil()',
|
||||
'JavaScript:abc',
|
||||
'evilNewProtocol:abc',
|
||||
' javascript:abc',
|
||||
' \n Java\n Script:abc',
|
||||
'javascript:',
|
||||
'javascript:',
|
||||
|
||||
Reference in New Issue
Block a user