2021-09-07 18:40:07 +08:00
|
|
|
/*
|
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
*/
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
|
|
|
const Template = require("../Template");
|
|
|
|
const HelperRuntimeModule = require("./HelperRuntimeModule");
|
|
|
|
|
2023-06-13 01:24:59 +08:00
|
|
|
/** @typedef {import("../Compilation")} Compilation */
|
|
|
|
|
2021-09-07 18:40:07 +08:00
|
|
|
class GetTrustedTypesPolicyRuntimeModule extends HelperRuntimeModule {
|
|
|
|
/**
|
2023-05-25 03:37:58 +08:00
|
|
|
* @param {ReadonlySet<string>} runtimeRequirements runtime requirements
|
2021-09-07 18:40:07 +08:00
|
|
|
*/
|
|
|
|
constructor(runtimeRequirements) {
|
|
|
|
super("trusted types policy");
|
|
|
|
this.runtimeRequirements = runtimeRequirements;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-06-17 01:13:03 +08:00
|
|
|
* @returns {string | null} runtime code
|
2021-09-07 18:40:07 +08:00
|
|
|
*/
|
|
|
|
generate() {
|
2023-06-13 01:24:59 +08:00
|
|
|
const compilation = /** @type {Compilation} */ (this.compilation);
|
2021-09-07 18:40:07 +08:00
|
|
|
const { runtimeTemplate, outputOptions } = compilation;
|
|
|
|
const { trustedTypes } = outputOptions;
|
|
|
|
const fn = RuntimeGlobals.getTrustedTypesPolicy;
|
Add option to continue on trusted-types policy-creation failure
Webpack already allows for specifying a trusted-types policy name. However, its current implementation is such that if a call to trustedTypes.createPolicy fails, the code will immediately stop executing. This isn't necessarily desirable, as an application could be in the early phases of rolling out trusted types, and thus have the CSP rule for trusted-types LibraryA LibraryB etc, BUT have require-trusted-types-for 'script' be in "report only" mode (Content-Security-Policy-Report-Only). In such a configuration, and when the webpacked code is dynamically-loaded into an application, adding the policy name to the webpack config will break old versions.
This PR keeps the original behavior, but introduces a new option for onPolicyCreationFailure: "continue" | "stop" (with "stop" remaining the default). If a developer chooses the "continue" option, the policy-creation will be wrapped in a try/catch. There is no security risk to this, since for host applications that DO have strict enforcement of trusted-types, the code will simply fail when the dangerous sink is used (e.g., when doing parseFromString). And likewise, wrapping in try/catch and doing nothing on catch is OK, because the code already deals with the possibility of the trustedTypes API not being available on the browser.
2023-04-20 05:53:22 +08:00
|
|
|
const wrapPolicyCreationInTryCatch = trustedTypes
|
|
|
|
? trustedTypes.onPolicyCreationFailure === "continue"
|
|
|
|
: false;
|
2021-09-07 18:40:07 +08:00
|
|
|
|
|
|
|
return Template.asString([
|
|
|
|
"var policy;",
|
|
|
|
`${fn} = ${runtimeTemplate.basicFunction("", [
|
|
|
|
"// Create Trusted Type policy if Trusted Types are available and the policy doesn't exist yet.",
|
|
|
|
"if (policy === undefined) {",
|
|
|
|
Template.indent([
|
|
|
|
"policy = {",
|
|
|
|
Template.indent(
|
|
|
|
[
|
|
|
|
...(this.runtimeRequirements.has(RuntimeGlobals.createScript)
|
|
|
|
? [
|
|
|
|
`createScript: ${runtimeTemplate.returningFunction(
|
|
|
|
"script",
|
|
|
|
"script"
|
|
|
|
)}`
|
2024-01-14 09:41:34 +08:00
|
|
|
]
|
2021-09-07 18:40:07 +08:00
|
|
|
: []),
|
|
|
|
...(this.runtimeRequirements.has(RuntimeGlobals.createScriptUrl)
|
|
|
|
? [
|
|
|
|
`createScriptURL: ${runtimeTemplate.returningFunction(
|
|
|
|
"url",
|
|
|
|
"url"
|
|
|
|
)}`
|
2024-01-14 09:41:34 +08:00
|
|
|
]
|
2021-09-07 18:40:07 +08:00
|
|
|
: [])
|
|
|
|
].join(",\n")
|
|
|
|
),
|
|
|
|
"};",
|
|
|
|
...(trustedTypes
|
|
|
|
? [
|
|
|
|
'if (typeof trustedTypes !== "undefined" && trustedTypes.createPolicy) {',
|
|
|
|
Template.indent([
|
Add option to continue on trusted-types policy-creation failure
Webpack already allows for specifying a trusted-types policy name. However, its current implementation is such that if a call to trustedTypes.createPolicy fails, the code will immediately stop executing. This isn't necessarily desirable, as an application could be in the early phases of rolling out trusted types, and thus have the CSP rule for trusted-types LibraryA LibraryB etc, BUT have require-trusted-types-for 'script' be in "report only" mode (Content-Security-Policy-Report-Only). In such a configuration, and when the webpacked code is dynamically-loaded into an application, adding the policy name to the webpack config will break old versions.
This PR keeps the original behavior, but introduces a new option for onPolicyCreationFailure: "continue" | "stop" (with "stop" remaining the default). If a developer chooses the "continue" option, the policy-creation will be wrapped in a try/catch. There is no security risk to this, since for host applications that DO have strict enforcement of trusted-types, the code will simply fail when the dangerous sink is used (e.g., when doing parseFromString). And likewise, wrapping in try/catch and doing nothing on catch is OK, because the code already deals with the possibility of the trustedTypes API not being available on the browser.
2023-04-20 05:53:22 +08:00
|
|
|
...(wrapPolicyCreationInTryCatch ? ["try {"] : []),
|
|
|
|
...[
|
|
|
|
`policy = trustedTypes.createPolicy(${JSON.stringify(
|
|
|
|
trustedTypes.policyName
|
|
|
|
)}, policy);`
|
|
|
|
].map(line =>
|
|
|
|
wrapPolicyCreationInTryCatch ? Template.indent(line) : line
|
|
|
|
),
|
|
|
|
...(wrapPolicyCreationInTryCatch
|
|
|
|
? [
|
|
|
|
"} catch (e) {",
|
|
|
|
Template.indent([
|
|
|
|
`console.warn('Could not create trusted-types policy ${JSON.stringify(
|
|
|
|
trustedTypes.policyName
|
|
|
|
)}');`
|
|
|
|
]),
|
|
|
|
"}"
|
2024-01-14 09:41:34 +08:00
|
|
|
]
|
Add option to continue on trusted-types policy-creation failure
Webpack already allows for specifying a trusted-types policy name. However, its current implementation is such that if a call to trustedTypes.createPolicy fails, the code will immediately stop executing. This isn't necessarily desirable, as an application could be in the early phases of rolling out trusted types, and thus have the CSP rule for trusted-types LibraryA LibraryB etc, BUT have require-trusted-types-for 'script' be in "report only" mode (Content-Security-Policy-Report-Only). In such a configuration, and when the webpacked code is dynamically-loaded into an application, adding the policy name to the webpack config will break old versions.
This PR keeps the original behavior, but introduces a new option for onPolicyCreationFailure: "continue" | "stop" (with "stop" remaining the default). If a developer chooses the "continue" option, the policy-creation will be wrapped in a try/catch. There is no security risk to this, since for host applications that DO have strict enforcement of trusted-types, the code will simply fail when the dangerous sink is used (e.g., when doing parseFromString). And likewise, wrapping in try/catch and doing nothing on catch is OK, because the code already deals with the possibility of the trustedTypes API not being available on the browser.
2023-04-20 05:53:22 +08:00
|
|
|
: [])
|
2021-09-07 18:40:07 +08:00
|
|
|
]),
|
|
|
|
"}"
|
2024-01-14 09:41:34 +08:00
|
|
|
]
|
2021-09-07 18:40:07 +08:00
|
|
|
: [])
|
|
|
|
]),
|
|
|
|
"}",
|
|
|
|
"return policy;"
|
|
|
|
])};`
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = GetTrustedTypesPolicyRuntimeModule;
|