vm2: TypeError: 'get' on proxy: property 'constants' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value

Noticed this while trying to require a dependency in a vm. Some code to reproduce:

const { NodeVM } = require("vm2");

const vm = new NodeVM({
  console: "redirect",
  sandbox: {},
  require: {
    builtin: ["fs"]
  },
  wrapper: "none"
});

vm.run("const fs = require('fs'); fs.constants");

Full stack trace:

node_modules/vm2/lib/main.js:327
			throw this._internal.Decontextify.value(e);
			^
TypeError: 'get' on proxy: property 'constants' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '[object Object]' but got '[object Object]')
    at Object.<anonymous> (vm.js:1:91)
    at NodeVM.run (node_modules/vm2/lib/main.js:325:27)
    at Object.<anonymous> (script.js:12:4)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)

Let me know if there’s any other information I can give you to be helpful!

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 15 (3 by maintainers)

Most upvoted comments

I met this error when i exported a ES6 class in the script used to run. it was ok after i translated it into
ES5.

Hey, any progress on this issue? I’m tried to use libraries like graceful-fs and got the same error.

Also ran into this error. I’m not familiar enough with proxies to understand why the current pattern is not ok but I was able to make the error go away by adding an extra check for readonly non-configurable properties in Contextify.object.get:

	object: function(object, traps, deepTraps, flags, mock) {
		const proxy = new host.Proxy(object, host.Object.assign({
			get: (target, key, receiver) => {
				if (key === 'vmProxyTarget' && DEBUG) return object;
				if (key === 'isVMProxy') return true;
				if (mock && key in mock) return mock[key];
				if (key === 'constructor') return Object;
				if (key === '__proto__') return Object.prototype;
                               
                                // Added code
				const config = host.Object.getOwnPropertyDescriptor(object, key);
				if (config && config.configurable === false && config.writable === false) {
					return object[key];
				}

This seems to follow the get invariant MDN describes:

The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable data property.

But it seems to me like it would break the sandboxing