Skip to content

Commit

Permalink
feat(compiler): add schema for Trusted Types sinks (#39554)
Browse files Browse the repository at this point in the history
Create a schema with an associated function to classify Trusted Types
sinks.

Piggyback a typo fix.

PR Close #39554
  • Loading branch information
bjarkler authored and AndrewKushnir committed Nov 23, 2020
1 parent c7f4abf commit 358c50e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/compiler/src/schema/dom_security_schema.ts
Expand Up @@ -19,7 +19,7 @@ import {SecurityContext} from '../core';
//
// =================================================================================================

/** Map from tagName|propertyName SecurityContext. Properties applying to all tags use '*'. */
/** Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'. */
let _SECURITY_SCHEMA!: {[k: string]: SecurityContext};

export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} {
Expand Down
47 changes: 47 additions & 0 deletions packages/compiler/src/schema/trusted_types_sinks.ts
@@ -0,0 +1,47 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/**
* Set of tagName|propertyName corresponding to Trusted Types sinks. Properties applying to all
* tags use '*'.
*
* Extracted from, and should be kept in sync with
* https://w3c.github.io/webappsec-trusted-types/dist/spec/#integrations
*/
const TRUSTED_TYPES_SINKS = new Set<string>([
// NOTE: All strings in this set *must* be lowercase!

// TrustedHTML
'iframe|srcdoc',
'*|innerhtml',
'*|outerhtml',

// NB: no TrustedScript here, as the corresponding tags are stripped by the compiler.

// TrustedScriptURL
'embed|src',
'object|codebase',
'object|data',
]);

/**
* isTrustedTypesSink returns true if the given property on the given DOM tag is a Trusted Types
* sink. In that case, use `ElementSchemaRegistry.securityContext` to determine which particular
* Trusted Type is required for values passed to the sink:
* - SecurityContext.HTML corresponds to TrustedHTML
* - SecurityContext.RESOURCE_URL corresponds to TrustedScriptURL
*/
export function isTrustedTypesSink(tagName: string, propName: string): boolean {
// Make sure comparisons are case insensitive, so that case differences between attribute and
// property names do not have a security impact.
tagName = tagName.toLowerCase();
propName = propName.toLowerCase();

return TRUSTED_TYPES_SINKS.has(tagName + '|' + propName) ||
TRUSTED_TYPES_SINKS.has('*|' + propName);
}
34 changes: 34 additions & 0 deletions packages/compiler/test/schema/trusted_types_sinks_spec.ts
@@ -0,0 +1,34 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {isTrustedTypesSink} from '@angular/compiler/src/schema/trusted_types_sinks';
import {describe, expect, it} from '@angular/core/testing/src/testing_internal';

{
describe('isTrustedTypesSink', () => {
it('should classify Trusted Types sinks', () => {
expect(isTrustedTypesSink('iframe', 'srcdoc')).toBeTrue();
expect(isTrustedTypesSink('p', 'innerHTML')).toBeTrue();
expect(isTrustedTypesSink('embed', 'src')).toBeTrue();
expect(isTrustedTypesSink('a', 'href')).toBeFalse();
expect(isTrustedTypesSink('base', 'href')).toBeFalse();
expect(isTrustedTypesSink('div', 'style')).toBeFalse();
});

it('should classify Trusted Types sinks case insensitive', () => {
expect(isTrustedTypesSink('p', 'iNnErHtMl')).toBeTrue();
expect(isTrustedTypesSink('p', 'formaction')).toBeFalse();
expect(isTrustedTypesSink('p', 'formAction')).toBeFalse();
});

it('should classify attributes as Trusted Types sinks', () => {
expect(isTrustedTypesSink('p', 'innerHtml')).toBeTrue();
expect(isTrustedTypesSink('p', 'formaction')).toBeFalse();
});
});
}

0 comments on commit 358c50e

Please sign in to comment.