From 81aa119739de36bb61a89f0a5e6fa2ae23247720 Mon Sep 17 00:00:00 2001 From: Bjarki Date: Sat, 10 Oct 2020 02:16:12 +0000 Subject: [PATCH] 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 --- packages/core/src/sanitization/sanitization.ts | 15 +++++++++------ .../core/test/sanitization/sanitization_spec.ts | 9 +++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/core/src/sanitization/sanitization.ts b/packages/core/src/sanitization/sanitization.ts index 2be379e468..54f4f272ad 100644 --- a/packages/core/src/sanitization/sanitization.ts +++ b/packages/core/src/sanitization/sanitization.ts @@ -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'); } diff --git a/packages/core/test/sanitization/sanitization_spec.ts b/packages/core/test/sanitization/sanitization_spec.ts index e144427a6d..435b0514f1 100644 --- a/packages/core/test/sanitization/sanitization_spec.ts +++ b/packages/core/test/sanitization/sanitization_spec.ts @@ -37,7 +37,7 @@ describe('sanitization', () => { .toEqual(''); expect(() => ɵɵsanitizeHtml(bypassSanitizationTrustUrl(''))) .toThrowError(/Required a safe HTML, got a URL/); - expect(ɵɵsanitizeHtml(bypassSanitizationTrustHtml(''))) + expect(ɵɵsanitizeHtml(bypassSanitizationTrustHtml('')).toString()) .toEqual(''); }); @@ -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'); });