feat(core): allow returning Trusted Types from SanitizerFn (#39218)

Sanitizers in Angular currently return strings, which will then
eventually make their way down to the DOM, e.g. as the value of an
attribute or property. This may cause a Trusted Types violation. As a
step towards fixing that, make it possible to return Trusted Types from
the SanitizerFn interface, which represents the internal sanitization
pipeline. DOM renderer interfaces are also updated to reflect the fact
that setAttribute and setAttributeNS must be able to accept Trusted
Types.

PR Close #39218
This commit is contained in:
Bjarki 2020-10-10 01:13:32 +00:00 committed by Andrew Kushnir
parent 765fa337e3
commit e8d47c2d41
3 changed files with 15 additions and 7 deletions

View File

@ -16,6 +16,7 @@
*/ */
import {RendererStyleFlags2, RendererType2} from '../../render/api'; import {RendererStyleFlags2, RendererType2} from '../../render/api';
import {TrustedHTML, TrustedScript, TrustedScriptURL} from '../../util/security/trusted_type_defs';
import {getDocument} from './document'; import {getDocument} from './document';
// TODO: cleanup once the code is merged in angular/angular // TODO: cleanup once the code is merged in angular/angular
@ -80,7 +81,9 @@ export interface ProceduralRenderer3 {
parentNode(node: RNode): RElement|null; parentNode(node: RNode): RElement|null;
nextSibling(node: RNode): RNode|null; nextSibling(node: RNode): RNode|null;
setAttribute(el: RElement, name: string, value: string, namespace?: string|null): void; setAttribute(
el: RElement, name: string, value: string|TrustedHTML|TrustedScript|TrustedScriptURL,
namespace?: string|null): void;
removeAttribute(el: RElement, name: string, namespace?: string|null): void; removeAttribute(el: RElement, name: string, namespace?: string|null): void;
addClass(el: RElement, name: string): void; addClass(el: RElement, name: string): void;
removeClass(el: RElement, name: string): void; removeClass(el: RElement, name: string): void;
@ -157,9 +160,11 @@ export interface RElement extends RNode {
classList: RDomTokenList; classList: RDomTokenList;
className: string; className: string;
textContent: string|null; textContent: string|null;
setAttribute(name: string, value: string): void; setAttribute(name: string, value: string|TrustedHTML|TrustedScript|TrustedScriptURL): void;
removeAttribute(name: string): void; removeAttribute(name: string): void;
setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void; setAttributeNS(
namespaceURI: string, qualifiedName: string,
value: string|TrustedHTML|TrustedScript|TrustedScriptURL): void;
addEventListener(type: string, listener: EventListener, useCapture?: boolean): void; addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
removeEventListener(type: string, listener?: EventListener, options?: boolean): void; removeEventListener(type: string, listener?: EventListener, options?: boolean): void;

View File

@ -6,7 +6,10 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {TrustedHTML, TrustedScript, TrustedScriptURL} from '../../util/security/trusted_type_defs';
/** /**
* Function used to sanitize the value before writing it into the renderer. * Function used to sanitize the value before writing it into the renderer.
*/ */
export type SanitizerFn = (value: any, tagName?: string, propName?: string) => string; export type SanitizerFn = (value: any, tagName?: string, propName?: string) =>
string|TrustedHTML|TrustedScript|TrustedScriptURL;

View File

@ -36,7 +36,7 @@ import {_sanitizeUrl as _sanitizeUrl} from './url_sanitizer';
* *
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵsanitizeHtml(unsafeHtml: any): 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 sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '';
@ -107,7 +107,7 @@ export function ɵɵsanitizeUrl(unsafeUrl: any): string {
* *
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): 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 sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '';
@ -130,7 +130,7 @@ export function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): string {
* *
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵsanitizeScript(unsafeScript: any): 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 sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '';