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:
parent
49197d12a0
commit
81aa119739
|
@ -12,6 +12,7 @@ import {getLView} from '../render3/state';
|
||||||
import {renderStringify} from '../render3/util/misc_utils';
|
import {renderStringify} from '../render3/util/misc_utils';
|
||||||
import {TrustedHTML, TrustedScript, TrustedScriptURL} from '../util/security/trusted_type_defs';
|
import {TrustedHTML, TrustedScript, TrustedScriptURL} from '../util/security/trusted_type_defs';
|
||||||
import {trustedHTMLFromString, trustedScriptFromString, trustedScriptURLFromString} from '../util/security/trusted_types';
|
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 {allowSanitizationBypassAndThrow, BypassType, unwrapSafeValue} from './bypass';
|
||||||
import {_sanitizeHtml as _sanitizeHtml} from './html_sanitizer';
|
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 {
|
export function ɵɵsanitizeHtml(unsafeHtml: any): TrustedHTML|string {
|
||||||
const sanitizer = getSanitizer();
|
const sanitizer = getSanitizer();
|
||||||
if (sanitizer) {
|
if (sanitizer) {
|
||||||
return sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '';
|
return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');
|
||||||
}
|
}
|
||||||
if (allowSanitizationBypassAndThrow(unsafeHtml, BypassType.Html)) {
|
if (allowSanitizationBypassAndThrow(unsafeHtml, BypassType.Html)) {
|
||||||
return unwrapSafeValue(unsafeHtml);
|
return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));
|
||||||
}
|
}
|
||||||
return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
|
return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
|
||||||
}
|
}
|
||||||
|
@ -110,10 +111,11 @@ export function ɵɵsanitizeUrl(unsafeUrl: any): string {
|
||||||
export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): TrustedScriptURL|string {
|
export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): TrustedScriptURL|string {
|
||||||
const sanitizer = getSanitizer();
|
const sanitizer = getSanitizer();
|
||||||
if (sanitizer) {
|
if (sanitizer) {
|
||||||
return sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '';
|
return trustedScriptURLFromStringBypass(
|
||||||
|
sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');
|
||||||
}
|
}
|
||||||
if (allowSanitizationBypassAndThrow(unsafeResourceUrl, BypassType.ResourceUrl)) {
|
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)');
|
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 {
|
export function ɵɵsanitizeScript(unsafeScript: any): TrustedScript|string {
|
||||||
const sanitizer = getSanitizer();
|
const sanitizer = getSanitizer();
|
||||||
if (sanitizer) {
|
if (sanitizer) {
|
||||||
return sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '';
|
return trustedScriptFromStringBypass(
|
||||||
|
sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');
|
||||||
}
|
}
|
||||||
if (allowSanitizationBypassAndThrow(unsafeScript, BypassType.Script)) {
|
if (allowSanitizationBypassAndThrow(unsafeScript, BypassType.Script)) {
|
||||||
return unwrapSafeValue(unsafeScript);
|
return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
|
||||||
}
|
}
|
||||||
throw new Error('unsafe value used in a script context');
|
throw new Error('unsafe value used in a script context');
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe('sanitization', () => {
|
||||||
.toEqual('<img src="unsafe:javascript:true">');
|
.toEqual('<img src="unsafe:javascript:true">');
|
||||||
expect(() => ɵɵsanitizeHtml(bypassSanitizationTrustUrl('<img src="javascript:true">')))
|
expect(() => ɵɵsanitizeHtml(bypassSanitizationTrustUrl('<img src="javascript:true">')))
|
||||||
.toThrowError(/Required a safe HTML, got a URL/);
|
.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">');
|
.toEqual('<img src="javascript:true">');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ describe('sanitization', () => {
|
||||||
expect(() => ɵɵsanitizeResourceUrl('javascript:true')).toThrowError(ERROR);
|
expect(() => ɵɵsanitizeResourceUrl('javascript:true')).toThrowError(ERROR);
|
||||||
expect(() => ɵɵsanitizeResourceUrl(bypassSanitizationTrustHtml('javascript:true')))
|
expect(() => ɵɵsanitizeResourceUrl(bypassSanitizationTrustHtml('javascript:true')))
|
||||||
.toThrowError(/Required a safe ResourceURL, got a HTML/);
|
.toThrowError(/Required a safe ResourceURL, got a HTML/);
|
||||||
expect(ɵɵsanitizeResourceUrl(bypassSanitizationTrustResourceUrl('javascript:true')))
|
expect(ɵɵsanitizeResourceUrl(bypassSanitizationTrustResourceUrl('javascript:true')).toString())
|
||||||
.toEqual('javascript:true');
|
.toEqual('javascript:true');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ describe('sanitization', () => {
|
||||||
expect(() => ɵɵsanitizeScript('true')).toThrowError(ERROR);
|
expect(() => ɵɵsanitizeScript('true')).toThrowError(ERROR);
|
||||||
expect(() => ɵɵsanitizeScript(bypassSanitizationTrustHtml('true')))
|
expect(() => ɵɵsanitizeScript(bypassSanitizationTrustHtml('true')))
|
||||||
.toThrowError(/Required a safe Script, got a HTML/);
|
.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', () => {
|
it('should select correct sanitizer for URL props', () => {
|
||||||
|
@ -114,7 +114,8 @@ describe('sanitization', () => {
|
||||||
bypassSanitizationTrustHtml('javascript:true'), 'iframe', 'src'))
|
bypassSanitizationTrustHtml('javascript:true'), 'iframe', 'src'))
|
||||||
.toThrowError(/Required a safe ResourceURL, got a HTML/);
|
.toThrowError(/Required a safe ResourceURL, got a HTML/);
|
||||||
expect(ɵɵsanitizeUrlOrResourceUrl(
|
expect(ɵɵsanitizeUrlOrResourceUrl(
|
||||||
bypassSanitizationTrustResourceUrl('javascript:true'), 'iframe', 'src'))
|
bypassSanitizationTrustResourceUrl('javascript:true'), 'iframe', 'src')
|
||||||
|
.toString())
|
||||||
.toEqual('javascript:true');
|
.toEqual('javascript:true');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue