Skip to content

Assumptions on new typeof values #374

@acutmore

Description

@acutmore

Hey, not an urgent issue. Just a heads up 😀

Right now doing typeof can only return "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function". This means code can currently safely assume that anything that is not object or function is primitive and inert, no need to wrap the value to prevent access to outside of the VM.

vm2/lib/contextify.js

Lines 563 to 564 in 4198060

default: // string, number, boolean, symbol
return value;

This assumption may not hold in the future depending on how the Record&Tuple proposal ends up being specified. It could mean that there is a value that returns "record" | "tuple" | "box" which then contains a direct reference to an object inside it.

One option to future proof against this is to explicitly add "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" to the switch and let those values pass, but don't pass on future unknown types by default until explicit support has been added.

case 'undefined':
  return undefined;
case 'string':
case 'number':
case 'bigint':
case 'boolean':
case 'symbol':
  return value;
default: // unexpected typeof - support not added yet
  return null;

Example of vm escape via Box

// Current safe usage:
const {VM} = require('vm2');

const vm = new VM({sandbox: {
    add: function(a, b) { return a + b }
}});

vm.run('add.constructor("process.exit()")()');  // ReferenceError [Error]: process is not defined
// Possible future unsafe usage:
const {VM} = require('vm2');

const vm = new VM({sandbox: {
    utils: #{
       add: Box(function(a, b) { return a + b })
    }
}});

vm.run('Box.unbox(utils.add).constructor("process.exit()")()');  // process does exit

The exact details around what should happen when a box is passed to a new realm are still being discussed so this might not ever be an issue, but wanted to give you a heads up that these discussions are happening.

tc39/proposal-record-tuple#260

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions