Question presented to candidate: "You need to evaluate a small, user-provided expression — a formula in a spreadsheet-like feature, say — without exposing your application's own variables and functions to it. Does Node's vm module actually give you that isolation, and is it a full security guarantee?"
What a strong answer should cover:
- Node's built-in
vmmodule compiles and runs JavaScript within a separate V8 context, with its own global object, distinct from the calling code's global scope —vm.createContext(sandbox)turns a plain object into that separate context's global scope. - 📌 Verified, not assumed: a real
vmsandbox genuinely could not see a variable set on the real Node global (typeof outerVarreturned"undefined"inside the sandbox), and avardeclared inside the sandbox did not leak out to the real global (confirmedundefinedthere) — it appeared instead as a property on the sandbox object itself. This is genuine two-way separation, not merely a naming convention. - A precise, important limitation, stated explicitly rather than glossed over:
vmis not a complete, airtight security sandbox for genuinely untrusted code — Node's own documentation is explicit that it provides isolation of variable scope, not a guarantee against denial-of-service (an infinite loop inside avmcontext still hangs, unless externally timed out) or every possible context-escape technique that has been found over the years. - The realistic, correct use cases: evaluating a known-shape, restricted expression (a spreadsheet formula, a simple templating expression) where the input is not fully adversarial, or building developer tooling (a REPL, a code sandbox for a trusted internal tool) — not running genuinely untrusted, potentially hostile third-party code with security guarantees riding on
vmalone. - For genuinely untrusted code needing a real security boundary, the correct answer is a stronger isolation layer — a separate OS process (with its own resource limits) or a dedicated, purpose-built sandboxing product — not
vmused in isolation. - A precise answer connects this directly to the dedicated
eval()-security-risks question:vmis the more structured, partially-isolated alternative to a bareeval(), but the word "partially" is load-bearing — it narrows the blast radius of variable/scope access, it does not eliminate every risk a fully adversarial input could pose.
Clarifying questions expected:
- "Is the input genuinely adversarial/untrusted, or a restricted, known-shape expression from a semi-trusted source?" — decides whether
vmalone is actually sufficient. - "Does the use case need to bound execution time/resource usage, not just variable scope?" —
vmalone does not provide that.
Code / implementation expected: Yes — the real, verified two-way isolation (a real global variable invisible inside the sandbox, and vice versa) is the concrete, convincing demonstration of what vm actually provides, paired honestly with what it does not.