Louis Christopher
Louis Christopher

Reputation: 368

Why do class/function constructors in JS evaluate strings as expressions?

I took a look at one of the rules from eslint-plugin-security and found that user input could in theory lead to a Remote Code Execution bug.

const a = class {};
console.log(a['constructor']);
a['constructor']('console.log(1)')();

function b() {}
console.log(b['constructor']);
b['constructor']('console.log(2)')();

const c = {}
console.log(c['constructor'])
console.log(c['constructor']('console.log(3)')());

From the snippet it's easy to see that constructors of classes and functions seem to parse strings and evaluate them as valid code. Objects for some reason don't exhibit this behaviour.

Why is this even allowed to happen? What feature of JavaScript needs this behaviour from function/class constructors? I'm assuming it's integral to the way JavaScript works otherwise I don't see why it hasn't been removed from the language.

Upvotes: 3

Views: 421

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371019

The problem is that the .constructor of a class is Function, and calling the Function constructor with a string creates a function from that string, and then calling that function results in the string's code being executed:

const a = class {};
console.dir(a['constructor'] === Function);
a['constructor']('console.log(1)')();

This isn't really any different from

Function('console.log(1)')();

It's just that a class's constructor property happens to point to the same thing.

Objects can exhibit the same property, if you navigate up to the .constructor property twice (first one accesses the Object constructor, second accesses the Function constructor):

const a = {};
console.dir(a['constructor'].constructor === Function);
a['constructor'].constructor('console.log(1)')();

If you allow arbitrary access to properties of any object, and also allow those properties to be called with arbitrary arguments, pretty much anything can be executed. The prototype chain (and .constructor) properties are useful, but like many things, they can be misused.

Upvotes: 7

Related Questions