Handlebars.js: Access control to proto properties

Created on 11 Jan 2020  ·  3Comments  ·  Source: handlebars-lang/handlebars.js

After the comments from #1633 and #1634 and the referenced issues, I think it would be a good idea to create a runtime option that allows to whitelist the prototype of a given class.

Calling the template wit

template ({some: "input object"}, { allowedPrototypes: [
  Test
] })

would allow a property to be resolved if the following is true.

parent[propertyName] === Test.prototype[propertyName] && Test.prototype.hasOwnProperty(propertyName)

I think it would be helpful when using custom classes in web-servers, because it is certainly not save to turn off prototype checks in such an environment.

I would like to have opinions about that.

feature

Most helpful comment

One potential problem is that users will expect that adding B to the allowed prototypes would work in this case:

class A { get a() { return 'a' } }
class B extends A {}

const parent = new B();
parent['a'] === B.prototype['a'] && B.prototype.hasOwnProperty('a') // => false

This isn't too bad, it just needs to be documented, but it would likely surprise quite a few people.

All 3 comments

One potential problem is that users will expect that adding B to the allowed prototypes would work in this case:

class A { get a() { return 'a' } }
class B extends A {}

const parent = new B();
parent['a'] === B.prototype['a'] && B.prototype.hasOwnProperty('a') // => false

This isn't too bad, it just needs to be documented, but it would likely surprise quite a few people.

We could also check if superclasses are whitelisted, so you only need to whitelist "A" in order to get properties from "A" and "B" accepted.

The other way around is more difficult, because it required blacklisting all native classes, which may change over time.

@nknapp Would it be possible to use getPrototypeOf and getOwnPropertyDescriptor to see if the getter was defined. I'm not sure if this regresses to the issues that were already fixed or not.

class Example {
  get hello() {
    return 'world';
  }
}

const obj = new Example();
console.log(obj.hello);
// "world"
console.log(Object.getOwnPropertyDescriptor(obj, 'hello'));
// undefined
console.log(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), 'hello'));
// { configurable: true, enumerable: false, get: function get hello() { return 'world'; }, set: undefined }

source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#get_Vs._defineProperty

Was this page helpful?
0 / 5 - 0 ratings