Closed ErikTheBerik closed 2 months ago
Bundling the javascript is the easiest way to get it all into isolated-vm
I'll attempt to bundle Vento.js into a single file using Rollup and integrate it with isolated-vm. I was hoping for an easier solution, but this seems like the best approach. If I encounter any issues, I'll update this thread; otherwise, I'll close the issue and share any relevant insights to assist others facing a similar situation in the future.
It really helps to think of isolated-vm like a web browser. How would you get ventojs into a web browser? You would bundle it. It just so happens that the tooling for web browsers is more developed so most people don't even think about it anymore.
That analogy makes a lot of sense. In terms of a browser bundling would be the logic approach, so I see why I should do the same in isolated-vm.
I have a question about file systems. As mentioned before, the Vento.js template I created outputs the contents of the .env file. If I bundle the full Vento.js module into isolated-vm, will isolated-vm still be able to fetch the contents of the .env file? Additionally, will it retain access to the same files that Node.js has access to?
If I think of it in terms of a browser, as long as the browser has file access, it can retrieve files from the host's computer. In this case, the host would be the server. But I assume isolated-vm doesn't actually have access to the filesystem, right?
JavaScript, the language, does not define any filesystem operations. isolated-vm is a plain JavaScript environment.
Ah, of course! If I want to access the contents of a file, I'd need to use a module like fs
. So, as long as I don't bundle such a module with Vento.js, attempting to fetch the contents of a file should simply fail—which is exactly the behavior I'm aiming for.
After trying to make this work, I realised I would need to rewrite a big chunk of the VentoJS code as it has dependencies to fs, fetch, etc. Instead I will be changing libraries to one that is already secure so I won't need to isolate anything.
I'm exploring using isolated-vm to safely execute untrusted VentoJS templates, which is a template engine similar to Nunjucks but can run arbitrary JavaScript. My goal is to isolate the JavaScript running within the Vento templates, restricting it to the isolated-vm environment while exposing only a controlled set of functions and variables.
Here is a very simple example of running some malicious ventojs template that will output the contents of .env:
What I'm Trying to Achieve:
My Current Approach:
Questions/Concerns:
Best Approach to Passing Modules: I understand that passing modules to the isolated context (such as VentoJS) is a common challenge, I have done some initial research and would like some guidance. Is it necessary to package the entire ventojs module into a single file (as mentioned by Issue #124 ), or is there a simpler way to achieve this isolation? Handling External I/O: Since I want to block direct file access but still allow certain functions (like network calls) outside the isolated environment, should I rely on wrapping functions in external contexts? Is there an example or pattern you’d recommend for handling these use cases securely?
Additional Notes:
I have no need to run untrusted JavaScript that interacts with the filesystem directly (e.g., no fs or file reads in the isolated-vm context). I’m hoping to avoid reinventing the wheel and would appreciate any guidance on best practices or existing solutions for isolating template engines like VentoJS or Nunjucks. I know that I'm not the first one to try this.
Any advice on how to properly set this up with isolated-vm, or examples of similar implementations, would be incredibly helpful!