vm2 icon indicating copy to clipboard operation
vm2 copied to clipboard

Support for running vm2 in browser

Open patriksimek opened this issue 7 years ago • 19 comments

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.

patriksimek avatar Jul 30 '17 23:07 patriksimek

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.

CapacitorSet avatar Jul 31 '17 14:07 CapacitorSet

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 avatar Jul 31 '17 23:07 io4

@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.

CapacitorSet avatar Aug 01 '17 06:08 CapacitorSet

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.

stale[bot] avatar Jan 27 '19 02:01 stale[bot]

Please don't close, this is a relevant issue.

jafetmorales avatar Jan 30 '19 00:01 jafetmorales

I'm thinking about using web workers to get vm2 working in browsers. I'll give it a shot.

patriksimek avatar Jan 30 '19 12:01 patriksimek

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.

jafetmorales avatar Jan 31 '19 19:01 jafetmorales

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 :)

patriksimek avatar Feb 01 '19 01:02 patriksimek

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?

jafetmorales avatar Feb 01 '19 02:02 jafetmorales

#227 is of interest, especially since Realms was mentioned specifically for browser sandboxing.

CapacitorSet avatar Aug 22 '19 19:08 CapacitorSet

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.

XmiliaH avatar Sep 19 '19 19:09 XmiliaH

@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.

john-doherty avatar Jan 14 '21 12:01 john-doherty

I don't know of a way to observe window or window.top in a way that allows to throw before something happens.

XmiliaH avatar Apr 08 '21 00:04 XmiliaH

Hi I need to import vm2.js as a module into typescript file. Can someone please help? Thank you

yalondpsi avatar May 01 '21 09:05 yalondpsi

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.

yalondpsi avatar May 02 '21 07:05 yalondpsi

Is support for vm2 in browser an actual thing or I need to use that long time branch ?

EFF avatar Feb 01 '22 18:02 EFF

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.

XmiliaH avatar Feb 01 '22 20:02 XmiliaH

This article from figma can help you https://www.figma.com/blog/how-we-built-the-figma-plugin-system/

SamuelHaidu avatar Aug 26 '22 21:08 SamuelHaidu

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:

  1. Sandbox (like Figma Plugin Sandbox, but better and easier to use);
  2. Protect JavaScript source code via AOT compiling to opcode.

linonetwo avatar May 03 '23 03:05 linonetwo