Skip to content

compartment-mapper: revisit findRedirect (dynamic requires) #2876

@boneskull

Description

@boneskull

What is the Problem Being Solved?

We currently support two use-cases where a compartment is allowed to use a dynamic require with an aboslute-path specifier to load a module in a different compartment:

  1. The module lives in a compartment which the requesting compartment already has access to
  2. The module lives in a compartment which has access to the requesting compartment

Point 1. is pretty obvious, but the reason for 2. is to support the node-gyp-build use case:

const path = require('node:path');
const myFoo = require('node-gyp-build')(path.join(__dirname, 'foo.node'));

In both of these cases, the compartment of the requested module already has a reference to node-gyp-build in its own compartment map.

I've identified a third use-case which will need addressing:

The module lives in a compartment whose ancestor has access to the requesting compartment.

The use-case comes from Webpack. Typically, a user has a webpack.config.js file. In this config file, you may declaratively specify loaders to process certain filetypes. Instead of actually importing these loaders in your config file, you provide just the package name(s) in the Webpack configuration (similarly to how ESLint-pre-v9 config files work).

During execution, when Webpack encounters a file it needs to hand to a configured loader, it imports the loader (likely via dynamic require). Unlike node-gyp-build, webpack itself does not perform the import; another module, loader-runner, does. This introduces a level of indirection that we do not currently account for. Nowhere does webpack.config.js's compartment know about the loaders, because they are not imported anywhere—even if they are direct dev dependencies of its package.

Description of the Design

"The module lives in a compartment whose ancestor has access to the requesting compartment" is just my initial impression of what we need.

I don't know of any way offhand to make this work other than referencing package policy; I can certainly tell policy that loader-runner can access a module in, e.g., babel-loader.

This may be the most feasible way forward.

Another strategy could be to leverage policy to make certain compartments "cascade" into the scopes of child compartments, though this sounds like both a morass (cycles!) and a slouchy security posture.

Other than that, I'm open to ideas because I am out of them.

Security Considerations

IMO, this shouldn't be any worse than the currently-supported use-cases.

Scaling Considerations

n/a

Test Plan

Happy path / sad path, fixtures, etc.

Compatibility Considerations

n/a

Upgrade Considerations

If the implementation and security implications feel skeevy, then the behavior should be opt-in, and NEWS.md should contain an entry for API changes.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions