fix(core): convert legacy-sanitized values to Trusted Types (#39218)

Use the bypass-specific Trusted Types policy for automatically upgrade
any values from custom sanitizers or the bypassSecurityTrust functions
to a Trusted Type. Update tests to reflect the new behavior.

PR Close #39218
This commit is contained in:
Bjarki 2020-10-10 02:16:12 +00:00 committed by Andrew Kushnir
parent 49197d12a0
commit 81aa119739
2 changed files with 14 additions and 10 deletions

View File

@ -12,6 +12,7 @@ import {getLView} from '../render3/state';
import {renderStringify} from '../render3/util/misc_utils';
import {TrustedHTML, TrustedScript, TrustedScriptURL} from '../util/security/trusted_type_defs';
import {trustedHTMLFromString, trustedScriptFromString, trustedScriptURLFromString} from '../util/security/trusted_types';
import {trustedHTMLFromStringBypass, trustedScriptFromStringBypass, trustedScriptURLFromStringBypass} from '../util/security/trusted_types_bypass';
import {allowSanitizationBypassAndThrow, BypassType, unwrapSafeValue} from './bypass';
import {_sanitizeHtml as _sanitizeHtml} from './html_sanitizer';
@ -39,10 +40,10 @@ import {_sanitizeUrl as _sanitizeUrl} from './url_sanitizer';
export function ɵɵsanitizeHtml(unsafeHtml: any): TrustedHTML|string {
const sanitizer = getSanitizer();
if (sanitizer) {
return sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '';
return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');
}
if (allowSanitizationBypassAndThrow(unsafeHtml, BypassType.Html)) {
return unwrapSafeValue(unsafeHtml);
return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));
}
return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
}
@ -110,10 +111,11 @@ export function ɵɵsanitizeUrl(unsafeUrl: any): string {
export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): TrustedScriptURL|string {
const sanitizer = getSanitizer();
if (sanitizer) {
return sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '';
return trustedScriptURLFromStringBypass(
sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');
}
if (allowSanitizationBypassAndThrow(unsafeResourceUrl, BypassType.ResourceUrl)) {
return unwrapSafeValue(unsafeResourceUrl);
return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
}
throw new Error('unsafe value used in a resource URL context (see http://g.co/ng/security#xss)');
}
@ -133,10 +135,11 @@ export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): TrustedScriptUR
export function ɵɵsanitizeScript(unsafeScript: any): TrustedScript|string {
const sanitizer = getSanitizer();
if (sanitizer) {
return sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '';
return trustedScriptFromStringBypass(
sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');
}
if (allowSanitizationBypassAndThrow(unsafeScript, BypassType.Script)) {
return unwrapSafeValue(unsafeScript);
return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
}
throw new Error('unsafe value used in a script context');
}

View File

@ -37,7 +37,7 @@ describe('sanitization', () => {
.toEqual('<img src="unsafe:javascript:true">');
expect(() => ɵɵsanitizeHtml(bypassSanitizationTrustUrl('<img src="javascript:true">')))
.toThrowError(/Required a safe HTML, got a URL/);
expect(ɵɵsanitizeHtml(bypassSanitizationTrustHtml('<img src="javascript:true">')))
expect(ɵɵsanitizeHtml(bypassSanitizationTrustHtml('<img src="javascript:true">')).toString())
.toEqual('<img src="javascript:true">');
});
@ -57,7 +57,7 @@ describe('sanitization', () => {
expect(() => ɵɵsanitizeResourceUrl('javascript:true')).toThrowError(ERROR);
expect(() => ɵɵsanitizeResourceUrl(bypassSanitizationTrustHtml('javascript:true')))
.toThrowError(/Required a safe ResourceURL, got a HTML/);
expect(ɵɵsanitizeResourceUrl(bypassSanitizationTrustResourceUrl('javascript:true')))
expect(ɵɵsanitizeResourceUrl(bypassSanitizationTrustResourceUrl('javascript:true')).toString())
.toEqual('javascript:true');
});
@ -78,7 +78,7 @@ describe('sanitization', () => {
expect(() => ɵɵsanitizeScript('true')).toThrowError(ERROR);
expect(() => ɵɵsanitizeScript(bypassSanitizationTrustHtml('true')))
.toThrowError(/Required a safe Script, got a HTML/);
expect(ɵɵsanitizeScript(bypassSanitizationTrustScript('true'))).toEqual('true');
expect(ɵɵsanitizeScript(bypassSanitizationTrustScript('true')).toString()).toEqual('true');
});
it('should select correct sanitizer for URL props', () => {
@ -114,7 +114,8 @@ describe('sanitization', () => {
bypassSanitizationTrustHtml('javascript:true'), 'iframe', 'src'))
.toThrowError(/Required a safe ResourceURL, got a HTML/);
expect(ɵɵsanitizeUrlOrResourceUrl(
bypassSanitizationTrustResourceUrl('javascript:true'), 'iframe', 'src'))
bypassSanitizationTrustResourceUrl('javascript:true'), 'iframe', 'src')
.toString())
.toEqual('javascript:true');
});