Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Conflicting Trusted Types Policies After Upgrading to v1.0.5 #8512

Closed
BrunoRDS opened this issue Nov 23, 2024 · 3 comments · Fixed by #8619
Closed

[Bug]: Conflicting Trusted Types Policies After Upgrading to v1.0.5 #8512

BrunoRDS opened this issue Nov 23, 2024 · 3 comments · Fixed by #8619
Assignees
Labels
bug Something isn't working

Comments

@BrunoRDS
Copy link

BrunoRDS commented Nov 23, 2024

System Info

System:
OS: Linux 6.5 Ubuntu 20.04.6 LTS (Focal Fossa)
CPU: (32) x64 Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
Memory: 109.55 GB / 125.78 GB
Container: Yes
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 20.11.0 - /usr/local/share/nvm/versions/node/v20.11.0/bin/node
Yarn: 1.23.19 - /usr/bin/yarn
npm: 10.2.4 - /usr/local/share/nvm/versions/node/v20.11.0/bin/npm
Browsers:
Edge: 131.0.2903.51

Details

After upgrading from RSPack v1.0.0-alpha.5 to v1.0.5, I encountered a conflict with Trusted Types policies. Specifically, one of my runtimes (loader.js) registers a Trusted Type policy under the default name, which causes issues when my main runtime (main.js) tries to register a policy under the same name. This is while running a local dev server in which my project uses devtool = "eval-cheap-module-source-map".

output.trustedTypes.policyName set to rspack-dev-server for the below error example:

main-06ce685d45bd6867.js:349 
 Refused to create a TrustedTypePolicy named 'rspack-dev-server' because a policy with that name already exists and the Content Security Policy directive does not 'allow-duplicates': "trusted-types...

Additional Information:

Before the update, the evals looked like this:

"./src/async-entry.ts": (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
    "use strict";
    eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */var _app_corestruct_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"../../corestruct/corestruct-polyfill/src/import-polyfills.ts\");\n/* harmony import *...

After the update, the evals look like this:

"./src/async-entry.ts": (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
    "use strict";
    eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* ESM import */var _app_corestruct_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(\"../../corestruct/corestruct-polyfill/src/import-polyfills.ts\");\n/* ESM import */...

__webpack_require__.ts will require __webpack_require__.tt of course.

also..
The new presence of the createScript function in the __webpack_require__.tt() function in the runtime:

createScript: function(script) {
    return script;
},

where before there was only createScriptUrl

These changes seem to point to this commit: #7866

@LingyuCoder

What is the recommended way of handling this default policy name collision w/ eval-cheap-module-source-map on?

I don't want / nor am able to (due to project policy) to enable allow-duplicates for CSP.
It would possibly be useful to have access to output.trustedTypes.onPolicyCreationFailure in the rspack config but it does not appear to be configurable.

Reproduce link

No response

Reproduce Steps

  1. Upgrade RSPack multi-page/multi-entry point project from v1.0.0-alpha.5 to v1.0.5 (or any later version up to 1.1.2)
    -- (Note: main.js must dependOn loader.js)
  2. Use devtool = "eval-cheap-module-source-map" in the dev server configuration.
  3. Use CSP (require-trusted-types-for": ["'script'"]) with trusted-type policies in the header, should be one of the allowed policy names.
  4. Observe the Trusted Types policy conflict between loader.js and main.js
@BrunoRDS BrunoRDS added bug Something isn't working pending triage The issue/PR is currently untouched. labels Nov 23, 2024
@LingyuCoder
Copy link
Contributor

I understand that you expect to be able to set different output.trustedTypes for different entries to prevent conflicts.

Currently rspack is the same behavior with webpack. By default, it is generated from output.uniqueName. When multiple entries are built in the same compilation, the output.trustedTypes value is the same.

So I think this should be avoid by:

  • using multi-compiler to set different configurations of output.trustedTypes
  • or using layer to set different configurations of output.trustedTypes
  • or using hooks.runtimeModule to override the runtime module which is named as webpack/runtime/get_trusted_types_policy to avoid creating policy twice.
  • or waiting for the onPolicyCreationFailure. It is indeed a configuration that rspack is missing. I will try to align it.

@LingyuCoder LingyuCoder self-assigned this Nov 26, 2024
@BrunoRDS
Copy link
Author

BrunoRDS commented Dec 2, 2024

So partially resolved, @LingyuCoder I don't know if you can point me towards what I am missing but I hope you can.

I went with your third bullet and added this plugin:

const PLUGIN_NAME = "CustomTrustedTypesPolicyPlugin";
const RUNTIME_MODULE_NAME = "get_trusted_types_policy";

class CustomTrustedTypesPolicyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
      compilation.hooks.runtimeModule.tap(PLUGIN_NAME, (module, chunk) => {
        if (
          module.name === RUNTIME_MODULE_NAME &&
          (chunk.name === "loader")
        ) {
          console.log(
            "CustomTrustedTypesPolicyPlugin: Found runtime module: ",
            module.name
          );
          console.log(`Module:\n\n ${JSON.stringify(module, null, 2)}`);
          // Ensure module.source is a string
          const source = module.source.source;
          const sourceString = Buffer.isBuffer(source)
            ? source.toString("utf-8")
            : source;
          if (typeof sourceString === "string") {
            // Regular expression to find the policy name
            const policyNameRegex = /trustedTypes\.createPolicy\("([^"]+)",/;
            const match = source.match(policyNameRegex);

            if (match && match[1]) {
              const policyName = match[1];
              const modifiedPolicyName = `${policyName}#${chunk.name}`;
              console.log(
                `Shift Policy Name: ${policyName} --> ${modifiedPolicyName}`
              );
              const modifiedSource = source.replace(
                policyName,
                modifiedPolicyName
              );

              console.log(`Modified Source: ${modifiedSource}`);
              module.source.source = Buffer.from(modifiedSource, "utf-8");
            } else {
              console.log("Policy name not found in the source.");
            }
          } else {
            console.log("Module source is not a string.");
          }
        }
      });
    });
  }
}

module.exports = CustomTrustedTypesPolicyPlugin;

Also adding in app#loader in the CSP trusted-types.

I no longer get a clash of policy names but now encounter a

ReferenceError: __webpack_require__ is not defined

error when some of my async entry file dynamic chunk import statements are evaluated:

for instance:

    "../../../node_modules/scheduler/cjs/scheduler.development.js": (function(__unused_webpack_module, exports) {
        "use strict";
        eval(__webpack_require__.ts("/**\n * @license React\n * scheduler.development.js <...>"));

    }

Which did not use to have the __webpack_require__.ts , Here it is with trusted types disabled (v1.1.3):

    "../../../node_modules/scheduler/cjs/scheduler.development.js": (function(__unused_webpack_module, exports) {
        "use strict";
        eval("/**\n * @license React\n * scheduler.development.js < ... >");
    }

I think this is likely just something I would have run into before with the TT being enabled w/ "eval-cheap-module-source-map" also in use, but I had not gotten here before in my apps initialization due to the duplicate TT policy issue.

@chenjiahan chenjiahan removed the pending triage The issue/PR is currently untouched. label Dec 3, 2024
@LingyuCoder
Copy link
Contributor

ReferenceError: webpack_require is not defined

Seems to be a bug here. I will try to fix it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants