forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(upgrade): Address Trusted Types violations in @angular/upgrade
Angular applications that are AngularJS hybrids are currently unable to adopt Trusted Types due to violations eminating from an innerHTML assignment in the @angular/upgrade package. This commit allows developers of such applications to optionally ignore this class of violations by configuring the Trusted Types header to allow the new angular#unsafe-upgrade policy. Note that the policy is explicitly labeled as unsafe as it does not in any way mitigate the security risk of using AngularJS in an Angular application, but does unblock Trusted Types adoption enabling XSS protection for other parts of the application. The implementation follows the approach taken in @angular/core; see packages/core/src/util/security.
- Loading branch information
Showing
4 changed files
with
131 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/** | ||
* @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 | ||
* the upgrade package. 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 {TrustedHTML, TrustedTypePolicy, TrustedTypePolicyFactory} from './trusted_types_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; | ||
|
||
/** | ||
* The type of window augmented with the Trusted Types policy factory. | ||
*/ | ||
type windowWithTrustedTypes = typeof window & {trustedTypes?: TrustedTypePolicyFactory}; | ||
|
||
/** | ||
* 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 ((window as windowWithTrustedTypes).trustedTypes) { | ||
try { | ||
policy = (window as windowWithTrustedTypes).trustedTypes!.createPolicy( | ||
'angular#unsafe-upgrade', | ||
{ | ||
createHTML: (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 legacy AngularJS template 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, the template string should | ||
* always be under full control of the application author, as untrusted input | ||
* can cause an XSS vulnerability. | ||
*/ | ||
export function trustedHTMLFromLegacyTemplate(html: string): TrustedHTML | string { | ||
return getPolicy()?.createHTML(html) || html; | ||
} |
42 changes: 42 additions & 0 deletions
42
packages/upgrade/src/common/src/security/trusted_types_defs.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/** | ||
* @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 | ||
* While Angular only uses Trusted Types internally for the time being, | ||
* references to Trusted Types could leak into our public API, which would force | ||
* anyone compiling against @angular/upgrade to provide the @types/trusted-types | ||
* package in their compilation unit. | ||
* | ||
* Until https://github.com/microsoft/TypeScript/issues/30024 is resolved, we | ||
* will keep Angular's public API surface free of references to Trusted Types. | ||
* For internal and semi-private APIs that need to reference Trusted Types, the | ||
* minimal type definitions for the Trusted Types API provided by this module | ||
* should be used instead. They are marked as "declare" to prevent them from | ||
* being renamed by compiler optimization. | ||
* | ||
* Adapted from | ||
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/trusted-types/index.d.ts | ||
* but restricted to the API surface used within Angular, mimicking the approach | ||
* in packages/core/src/util/security/trusted_type_defs.ts. | ||
*/ | ||
|
||
export type TrustedHTML = string & { | ||
__brand__: 'TrustedHTML'; | ||
}; | ||
|
||
export interface TrustedTypePolicyFactory { | ||
createPolicy( | ||
policyName: string, | ||
policyOptions: {createHTML?: (input: string) => string}, | ||
): TrustedTypePolicy; | ||
} | ||
|
||
export interface TrustedTypePolicy { | ||
createHTML(input: string): TrustedHTML; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters