Open caridy opened 6 years ago
Seems like, by the time all these changes are made, the result wouldn't be much different from the current class fields proposal (modulo private name declarations outside classes, which have already been under discussion in the context of the other proposal).
@littledan I think that’s true. But from my perspective, “private name declarations outside classes” is the key thing. What continues to make me nervous about the current proposal is mainly that “outside classes” seemed to be left as a problem-to-solve-later. In other words, it’s hard to get on board with a particular higher-level abstraction when the building-blocks form is left as an open question, especially when you anticipate needing the latter more often than the former, and it seems contrary to minmax principles to not introduce the lower level tool first (or at least concurrently).
To restate for my own benefit:
Symbol.private
can be hijacked to observe private symbol creation.For these reasons (according to the argument), it is better to provide a syntax-only solution, where private "key" creation and private state installation on objects is only allowed via syntax.
I think these are fair points and will be responding to them soon. Thanks!
@zenparsing regarding bullet 2, I see that as a positive facet of this proposal, since being able to do something inadvertently is an unavoidable consequence of being able to do something intentionally. Is there any feature which cannot be used badly?
regarding bullet 2, I see that as a positive facet of this proposal
I agree, but not for the same reason. I think this is a leak in branding, not a leak in encapsulation. It's impossible for foreign object to access its new private field unless is uses the foo.p.disable
method (or any other methods with the privateSymbol
in scope) so it seems perfectly encapsulated. But I can no longer guarantee that the foreign object isn't an instance of foo
which is just branding (and better left to WeakSet
s according to this proposal.
In this proposal Symbol.private can be hijacked to observe private symbol creation.
This point keeps coming up, but i think any syntax you could come up with to mitigate this will never truely archive this lofty goal.
It almost feels like a false sense of privacy. For as long as the author can control when the script is loaded they can hijack private state, syntax or otherwise. And if they can't then it follows that they can't do the same with Symbol.private
.
As an example example with hash#private
syntax.
Exhibit A: I could just import the script as text and replace all occurrences removing the declarative #private
syntax, and load/import the script inline as js
to the pleasure of my nefarious needs. In a node environment this is made even easier.
@thysultan to do so, you must either be in control of the execution of the program (you're the puppets' master), or your code executes before the other code so you could modify the environment to take control of the execution of the code-to-be-executed, so you can parse and evaluate the new code at will. This is not that simple, and in most cases, imposible due to other security layers (e.g.: CSP in browsers).
On the other hand, Symbol.private
being an API, it means that any code that has access to that API could replace it, so any newly created symbol is now observable. Our frozen realm proposal is supposed to protect again this particular case by freezing all those APIs to prevent taming, but we have a long road ahead before we can get that into browsers.
Nevertheless, these are the kind of things that some of us, at the TC39 committee, care about, and try to be coherent with other proposals.
or your code executes before the other code so you could modify the environment to take control of the execution of the code-to-be-executed, so you can parse and evaluate the new code at will. This is not that simple, and in most cases, imposible due to other security layers (e.g.: CSP in browsers).
@caridy Not necessarily. Exhibit B: Being the last script to load in a browser context – you could for example scrap all scripts in document.scripts
extract the contents of the scripts you want, and create new script elements with the modifier content or dynamically import inline encoded urls. That is to say i'm not aware of any hard blockers in CSP that could prevent this.
If a desired recipient is keen on accessing a private field, first-class syntax support won't prevent them from achieving this goal.
One of the big issues that we have identified when working with private fields, and the potential generalization of private fields is the leakage of them. Issue #2 and #7 are examples of such leakage, other examples are:
Symbol.private
to collect all new private symbols.class foo { disable() { this[privateSymbol] = false; } }
).As part of the generalization of private fields we found two mitigation strategies to address both of these issues, and I think this proposal can use them:
Number one is fairly simple, something like
private #foo
or something similar could be enough, while number two is more complicated. @erights will probably argue that in fact we need grammar for installation, initialization and access. With those mechanism in place, branding is possible, and leaking is impossible.In general, even though I haven't read thru the whole thing, this as a lot of similarities with the pseudo proposal for the generalization the private fields.