feat(core): create a Trusted Types policy for bypass conversions (#39218)
When an application uses a custom sanitizer or one of the bypassSecurityTrust functions, Angular has no way of knowing whether they are implemented in a secure way. (It doesn't even know if they're introduced by the application or by a shady third-party dependency.) Thus using Angular's main Trusted Types policy to bless values coming from these two sources would undermine the security that Trusted Types brings. Instead, introduce a Trusted Types policy called angular#unsafe-bypass specifically for blessing values from these sources. This allows an application to enforce Trusted Types even if their application uses a custom sanitizer or the bypassSecurityTrust functions, knowing that compromises to either of these two sources may lead to arbitrary script execution. In the future Angular will provide a way to implement custom sanitizers in a manner that makes better use of Trusted Types. PR Close #39218
This commit is contained in:
parent
9ec2bad4dc
commit
49197d12a0
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview
|
||||
* A module to facilitate use of a Trusted Types policy internally within
|
||||
* Angular specifically for bypassSecurityTrust* and custom sanitizers. It
|
||||
* lazily constructs the Trusted Types policy, providing helper utilities for
|
||||
* promoting strings to Trusted Types. When Trusted Types are not available,
|
||||
* strings are used as a fallback.
|
||||
* @security All use of this module is security-sensitive and should go through
|
||||
* security review.
|
||||
*/
|
||||
|
||||
import {global} from '../global';
|
||||
import {TrustedHTML, TrustedScript, TrustedScriptURL, TrustedTypePolicy, TrustedTypePolicyFactory} from './trusted_type_defs';
|
||||
|
||||
/**
|
||||
* The Trusted Types policy, or null if Trusted Types are not
|
||||
* enabled/supported, or undefined if the policy has not been created yet.
|
||||
*/
|
||||
let policy: TrustedTypePolicy|null|undefined;
|
||||
|
||||
/**
|
||||
* Returns the Trusted Types policy, or null if Trusted Types are not
|
||||
* enabled/supported. The first call to this function will create the policy.
|
||||
*/
|
||||
function getPolicy(): TrustedTypePolicy|null {
|
||||
if (policy === undefined) {
|
||||
policy = null;
|
||||
if (global.trustedTypes) {
|
||||
try {
|
||||
policy = (global.trustedTypes as TrustedTypePolicyFactory)
|
||||
.createPolicy('angular#unsafe-bypass', {
|
||||
createHTML: (s: string) => s,
|
||||
createScript: (s: string) => s,
|
||||
createScriptURL: (s: string) => s,
|
||||
});
|
||||
} catch {
|
||||
// trustedTypes.createPolicy throws if called with a name that is
|
||||
// already registered, even in report-only mode. Until the API changes,
|
||||
// catch the error not to break the applications functionally. In such
|
||||
// cases, the code will fall back to using strings.
|
||||
}
|
||||
}
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafely promote a string to a TrustedHTML, falling back to strings when
|
||||
* Trusted Types are not available.
|
||||
* @security This is a security-sensitive function; any use of this function
|
||||
* must go through security review. In particular, it must be assured that it
|
||||
* is only passed strings that come directly from custom sanitizers or the
|
||||
* bypassSecurityTrust* functions.
|
||||
*/
|
||||
export function trustedHTMLFromStringBypass(html: string): TrustedHTML|string {
|
||||
return getPolicy()?.createHTML(html) || html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafely promote a string to a TrustedScript, falling back to strings when
|
||||
* Trusted Types are not available.
|
||||
* @security This is a security-sensitive function; any use of this function
|
||||
* must go through security review. In particular, it must be assured that it
|
||||
* is only passed strings that come directly from custom sanitizers or the
|
||||
* bypassSecurityTrust* functions.
|
||||
*/
|
||||
export function trustedScriptFromStringBypass(script: string): TrustedScript|string {
|
||||
return getPolicy()?.createScript(script) || script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafely promote a string to a TrustedScriptURL, falling back to strings
|
||||
* when Trusted Types are not available.
|
||||
* @security This is a security-sensitive function; any use of this function
|
||||
* must go through security review. In particular, it must be assured that it
|
||||
* is only passed strings that come directly from custom sanitizers or the
|
||||
* bypassSecurityTrust* functions.
|
||||
*/
|
||||
export function trustedScriptURLFromStringBypass(url: string): TrustedScriptURL|string {
|
||||
return getPolicy()?.createScriptURL(url) || url;
|
||||
}
|
Loading…
Reference in New Issue