docs: Clarification around real world risks and use cases of VM module #40718
Description
📗 API Reference Docs Problem
-
Version: n/a
-
Platform: n/a
-
Subsystem: VM
Affected URL(s):
Description
Apologies if this isn't the appropriate place for this; I wasn't sure if it fell under help versus docs versus somewhere else.
The official docs for the VM module state the following in the first line of it's description.
The
vm
module is not a security mechanism. Do not use it to run untrusted code.
The last line of the Example: Running an HTTP server within a VM section says:
This may introduce risks when untrusted code is executed, e.g. altering objects in the context in unwanted ways.
Now, I think it's fairly safe to say it's quite clear that blindly running arbitrary code through the vm
module (or anything else) is most definitely not secure or safe. Although the second quote is a bit less definitive and things like the contextCodeGeneration
option in runInNewContext
are almost a bit of a teaser that might lead people to believe in some cases it is okay, but ultimately I digress :)
This issue is two-fold:
First, I'm curious if it's possible to have additional context (no pun intended) about when the vm
module is useful in practice to the average developer. I think it's safe to say a lot of people misunderstand it, and in some cases that can have very bad security consequences.
Second, I'm curious if it's possible to elaborate on situations where using the vm
module in restricted/well-defined situations it could be safe to run code under certain conditions. The following is a contrived example and one could argue it's not even an example of untrusted code, but I'm hoping it'll at least illustrate the idea.
Say for example you take an expression and parse it into an AST and validate that it only includes certain nodes. For sake of argument, let's say you only accept identifiers, numeric literals, and operators like <
, >
, ==
, and &&
. Now take the following example:
const vm = require('vm');
const code = 'apple == 5 && blueberry > 10';
const ctx = Object.create(null);
ctx.apple = 55;
ctx.blueberry = 33;
const myBool = vm.runInNewContext(code, ctx, { contextCodeGeneration: { strings: false } });
Now, you could certainly argue if you're parsing a string into an AST, validating the nodes, etc. that you aren't really running untrusted code at that point, but bear with me. Is this even a valid use case for the module? Is this even safe assuming you can validate the AST and the context you're passing in? Does this make you want to hit your head against your desk? :P
Ultimately, there are obviously other ways to do this, you're already parsing it out, you could just make your own logic to piece it back together without ever running the actual code itself, but this seems like a simple way to actually achieve evaluation of simple JS expressions, among other potential use cases, etc.
I think the vm
module is one of the most misunderstood modules out there, because a lot of developers I've talked with either completely misunderstand what it does, how you'd use it, or why you'd even use it, along with the potential for horrible security consequences when used inappropriately. It'd be awesome if the docs could include some more information on the practical side of things and where the module really shines in real world usage. Telling people when not to use something is certainly value added, but also illustrating real world use cases for when you would want to use it can be equally valuable.
- I would like to work on this issue and
submit a pull request.