lowclass icon indicating copy to clipboard operation
lowclass copied to clipboard

Prevent access of protected props with prototype manipulation

Open trusktr opened this issue 7 years ago • 1 comments

The following example from https://github.com/tc39/ecma262/issues/1341#issuecomment-439589889 shows a way to gain access to the protected members due to having access to the instance's class via the .constructor prop:

const T = Class(({ Protected }) => class {
  constructor() {
    Protected(this).v = 'T';
  }
});

const t = new T();

function extractTheDeets(V) {
  const S = Class(({ Protected }) => class extends V.constructor {
    constructor() {
      super();
      const original = Object.getPrototypeOf(V);
      Object.setPrototypeOf(V, S.prototype);
      const p = Protected(V);
      Object.setPrototypeOf(V, original);
      return p;
    }
  });
  return new S();
}

extractTheDeets(t);

It only works with Protected, not Private.

We can prevent it with a simple monkey patch of the Object.get/setPrototypeOf or __proto__ descriptors. Is there another way?

We could also delete the .constructor prop and provide a Static helper for accessing static members without revealing the class constructor. Does anyone ever need the .constructor prop for anything other than accessing static members?


Another example (using infamous):

const scene = document.querySelector('i-scene')

const Test = infamous.Class('Test').extends(infamous.Scene, ({ Protected }) => ({
	constructor() {
		debugger
		const proto = scene.__proto__
		scene.__proto__ = Test.prototype
		console.log(Protected(scene)._props)
		scene.__proto__ = proto
	},
}))

new Test

trusktr avatar Nov 19 '18 04:11 trusktr

We can prevent prototype from being modified with lockPrototype, which would prevent the unauthorized public access of the protected members in @devsnek's example.

trusktr avatar Apr 15 '19 20:04 trusktr