vm2
vm2 copied to clipboard
Support for running vm2 in browser
Branch: https://github.com/patriksimek/vm2/tree/feature-browsers Library: https://github.com/patriksimek/vm2/blob/feature-browsers/dist/vm2.js
Usage
<script src="vm2.js"></script>
<script>
const vm = new vm2.VM();
alert(vm.run('Math.random()'));
</script>
Issues
- Sandbox can be escaped via
window.top
.
TODO
- Remove
NodeVM
from browser version. - Add
BrowserVM
to browser version with browser related features. - Automated browser tests.
A somewhat hacky solution could involve AST rewriting to manually wrap each property access. For instance, let x = foo.bar
would be rewritten to let x = (x => (x == window.top) ? (some patch here) : x)(foo.bar)
.
Here is an example of AST rewriting, where function call nodes are wrapped in nodes like this.
The disadvantages to this approach are that you can't easily debug the rewritten code, and that it takes some workarounds to deal with Function, eval and the like.
I think the only way is very heavyweight that is to basically interpret JS yourself, or to replace Functions constructions with a custom implementation (such as inject variable and parse content). This method would be very hard to implement.
Variable deletion is impossible due to variables like document
and top
that can not be deleted nor overwritten.
@io4, replacing Function, eval and the like at runtime is certainly possible with AST rewriting and it's not terribly difficult either. However, it does incur a heavy performance hit, both at "compile time" since you have to rewrite literally every function call and at runtime since function calls have to go through one layer of indirection.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Please don't close, this is a relevant issue.
I'm thinking about using web workers to get vm2 working in browsers. I'll give it a shot.
Maybe you can put it inside a sandboxed iframe as well. That way if it escapes, it's still restricted to the frame and cannot navigate the top level browsing context.
The status is we can't use web workers because they don't share a memory with the host. I was testing the sandboxed iframe, but no success there either. Without the allow-same-origin
option, vm2 doesn't even start. With that option enabled, I can access the top-level window. But I'm not giving up :)
What kind of error did it give you? Did it need to access a variable? Was it missing a library? Any data that could be retrieved by exchanging messages between iframes?
#227 is of interest, especially since Realms was mentioned specifically for browser sandboxing.
I did try to fix the access to window with the same trick as realms-shim does. A implementaition can be found here: https://github.com/XmiliaH/vm2/blob/feature-browsers/lib/vm.js Disadvantage is that everthing in the vm runs in strict mode.
@patriksimek to get around the window.top
issue, could you not observe the object and kill the script (throw and error) if modified/used? So, observe properties and wrap functions
Branch: https://github.com/patriksimek/vm2/tree/feature-browsers Library: https://github.com/patriksimek/vm2/blob/feature-browsers/dist/vm2.js
Usage
<script src="vm2.js"></script> <script> const vm = new vm2.VM(); alert(vm.run('Math.random()')); </script>
Issues
- Sandbox can be escaped via
window.top
.TODO
- Remove
NodeVM
from browser version.- Add
BrowserVM
to browser version with browser related features.- Automated browser tests.
I don't know of a way to observe window
or window.top
in a way that allows to throw before something happens.
Hi I need to import vm2.js as a module into typescript file. Can someone please help? Thank you
Hi I need to import vm2.js as a module into typescript file. Can someone please help? Thank you
Working as a module: added module.exports = vm2;
in the end of file.
Is support for vm2 in browser an actual thing or I need to use that long time branch ?
As far as I know running the master branch in a browser is not safe due to access to the window global. There is a branch with browser support, however, it is outdated and insecure.
This article from figma can help you https://www.figma.com/blog/how-we-built-the-figma-plugin-system/
https://github.com/sablejs/sablejs can be an alternative that can run in the nodejs and browser.
The safer and faster ECMA5.1 interpreter written by JavaScript, it can be used:
- Sandbox (like Figma Plugin Sandbox, but better and easier to use);
- Protect JavaScript source code via AOT compiling to opcode.