-
Notifications
You must be signed in to change notification settings - Fork 77
fix(compartment-mapper): specifier of module descriptor returned from findRedirect fixed #2765
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
base: master
Are you sure you want to change the base?
Conversation
@@ -418,3 +418,45 @@ test('sync module transforms work without dynamic require support', async t => { | |||
|
|||
t.is(transformCount, 2); | |||
}); | |||
|
|||
test('dynamic require of missing module falls through to importNowHook', async t => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you point out which test is covering the situation where findRedirect finds the redirect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any test which contains a fixture which is absolute-requiring something is. ... which is most of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specifically, this test covers the same sort of configuration as we encountered:
hooked-app
statically requires packagehooked
hooked
dynamically requires packagedynamic
by absolute pathdynamic
dynamically requires packageis-ok
by absolute pathis-ok
statically requires packageis-not-ok
@@ -692,7 +701,6 @@ export function makeImportNowHookMaker( | |||
compartmentDescriptors, | |||
compartments, | |||
absoluteModuleSpecifier: moduleSpecifier, | |||
packageLocation, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still believe we should not continue with an absolute path if findRedirect returns undefined. Any new findings to counter that since we talked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like findRedirect
fails to find absolute paths to compartment-relative modules which were not already mentioned. For example, if we try to require(require.resolve('./good.js'))
—and there are no existing ModuleDescriptor
s for a ./good.js
in the compartment descriptor—then findRedirect
will return undefined
. We need to let it bounce on the trampoline to find the file. If the file still can't be found, then we fall through to the hook-of-last-resort (exit hook).
That said, maybe it would be prudent to rewrite the path as relative to the compartment's location before we continue (though it "works" as-is).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, maybe it would be prudent to rewrite the path as relative to the compartment's location before we continue (though it "works" as-is).
I did this and it was wrong as pointed out by @naugtur. Reverted it
ca8d0ef
to
c051e7c
Compare
OK, this is ready |
c051e7c
to
41c4494
Compare
8c74957
to
0744b25
Compare
I've had to change the
This preserves support for This test covers the situation where we have a dynamic require of a module requested by absolute path which is found successfully via |
d51b21c
to
9c86393
Compare
} | ||
|
||
// we might have an absolute path here, but it might be within the compartment, so | ||
// we will try to find it. | ||
const candidates = nominateCandidates(moduleSpecifier, searchSuffixes); | ||
|
||
const record = syncTrampoline( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIR going into chooseModuleDescriptor
with an absolute path can result in an error that got us to find this issue in the first place. Some of the nested functionality is not ready to handle absolute paths. If the path is within the current compartment, we should be able to convert it to relative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so your recommendation would be to convert it to relative if the path is in the current compartment?
f08e0d9
to
11c99a9
Compare
… findRedirect fixed `findRedirect`, which is part of `importNowHook`, is called when we encounter a dynamic require where the specifier is an absolute path. Previous to this change, the `RedirectStaticModuleInterface` (a `ModuleDescriptor`) could contain an absolute path. Absolute paths are not generally assumed by `ses` or `@endo/compartment-mapper`. In the situation where the module referenced in the `RedirectStaticModuleInterface` itself imports _another_ package (via mutual recursion & trampolining), these assumptions were violated and we made an attempt to call `resolve()` (from the `node-module-specifier` module) using its absolute path as the referrer, which is explicitly disallowed by `resolve()`; it throws an exception. To that end, we need to ensure that whatever `ModuleDescriptor` we return from `importNowHook` with is one where its `specifier` is relative to its package location. The fact that this nominally "worked" against our tests in both `@endo/compartment-mapper` _and_ `@lavamoat/node` was due to a) chance, and b) lack of a test case against a fixture representing this configuration. In addition, I removed the `packageLocation` parameter from `findRedirect`'s options bucket since it was serving no practical purpose (as noticed by @naugtur). I need to add two more tests against fixtures: 1. A fixture which is similar to the configuration mentioned above 2. A fixture where the dynamically-required file is in a different compartment (which should be subject to policy enforcement)
This ensures the case that we found where a package which was required dynamically via an absolute path attempts to require yet another package
Co-authored-by: Zbyszek Tenerowicz <[email protected]>
11c99a9
to
c1b8bb5
Compare
Description
findRedirect
, which is part ofimportNowHook
, is called when we encounter a dynamic require where the specifier is an absolute path.Previous to this change, the
RedirectStaticModuleInterface
(aModuleDescriptor
) could contain an absolute path. Absolute paths are not generally assumed byses
or@endo/compartment-mapper
. In the situation where the module referenced in theRedirectStaticModuleInterface
itself imports another package (via mutual recursion & trampolining), these assumptions were violated and we made an attempt to callresolve()
(from thenode-module-specifier
module) using its absolute path as the referrer, which is explicitly disallowed byresolve()
; it throws an exception.To that end, we need to ensure that whatever
ModuleDescriptor
we return fromimportNowHook
with is one where itsspecifier
is relative to its package location.The fact that this nominally "worked" against our tests in both
@endo/compartment-mapper
and@lavamoat/node
was due to a) chance, and b) lack of a test case against a fixture representing this configuration.In addition, I removed the
packageLocation
parameter fromfindRedirect
's options bucket since it was serving no practical purpose (as noticed by @naugtur).Security Considerations
None that I am aware of
Scaling Considerations
no
Documentation Considerations
This is a bugfix
Testing Considerations
I need to add two more tests against fixtures before I publish this:
Compatibility Considerations
None that I am aware of
Upgrade Considerations
Not breaking. Probably not worth a note in
NEWS.md