feat(compiler): add schema for Trusted Types sinks (#39554)
Create a schema with an associated function to classify Trusted Types sinks. Piggyback a typo fix. PR Close #39554
This commit is contained in:
parent
c7f4abf18a
commit
358c50e226
@ -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};
|
let _SECURITY_SCHEMA!: {[k: string]: SecurityContext};
|
||||||
|
|
||||||
export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} {
|
export function SECURITY_SCHEMA(): {[k: string]: SecurityContext} {
|
||||||
|
47
packages/compiler/src/schema/trusted_types_sinks.ts
Normal file
47
packages/compiler/src/schema/trusted_types_sinks.ts
Normal file
@ -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
packages/compiler/test/schema/trusted_types_sinks_spec.ts
Normal file
34
packages/compiler/test/schema/trusted_types_sinks_spec.ts
Normal file
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user