endojs / endo

Endo is a distributed secure JavaScript sandbox, based on SES
Apache License 2.0
762 stars 68 forks source link

fix(compartment-mapper): Take only first matching tag of package exports #2275

Closed kriskowal closed 1 month ago

kriskowal commented 1 month ago

Closes: #2276

Description

If a package.json "exports" is a list of ordered constraints, Endo’s Compartment Mapper currently uses all of the accepted entries and not just the first. This causes subsequent entries to override the first if they produce matching paths. I believe the intended behavior is to use the first that matches.

Security Considerations

This amounts to a difference in behavior between Endo and Node in the treatment of Package Exports.

Scaling Considerations

None.

Documentation Considerations

Fixing this issue will bring Endo into accord with Node.js’s somewhat light documentation on this feature.

Testing Considerations

Existing snapshot tests cover the behavior and must be updated to reflect the correct interpretation.

Compatibility Considerations

This will improve ecosystem compatibility. No known bundles depend on the existing behavior, but we cannot rule out the possibility.

There is a possibility that this change will break existing bundles that depend on the current erroneous behavior, for example preferring default over an endo tag. I am considering this a bugfix and not a breaking change since it is a bug to rely on the current behavior.

Upgrade Considerations

Even if this behavior might break the bundling process for existing contracts, it will not invalidate existing bundles. This change should not break upgrades but may create a speed bump for upgrading tool dependencies.

kriskowal commented 1 month ago

@naugtur I’m interested in your take on whether this fix or the breaking tests are invalid.

naugtur commented 1 month ago

This might surface incompatibilities we didn't discover earlier if they were overshadowed by later entries but that would be the only way it could break anyone.

I could argue it should be a break instead of a return.

I'm not sure whether this or the previous state was the desired behavior - if we have entries for import and Endo, regardless of order, we should probably prefer endo if someone has put in the effort to supply it.

So maybe tags need to be an ordered list that we check in order and pick one based on that.

kriskowal commented 1 month ago

Spot checking the snapshot tests, I’m convinced that the new behavior is consistent with Node.js’s design. I’m posting an update with updated snapshots.

naugtur commented 1 month ago

I'll think if I can come up with counterexamples