Re: [webcomponents] Encapsulation and defaulting to open vs closed (was in www-style)

On Thu, Feb 13, 2014 at 1:25 PM, Maciej Stachowiak <> wrote:

> On Feb 12, 2014, at 4:04 PM, Alex Russell <> wrote:
> In discussion with Elliot and Erik, there appears to be an additional
> complication: any of the DOM manipulation methods that aren't locked down
> (marked non-configurable and filtered, ala caja) create avenues to get
> elements from the Shadow DOM and then inject styles. E.g., even with Arv's
> lockdown sketch:
> You still have most of your work ahead of you. DocumentFragment provides
> tons of "ins", as will all incidentally composed APIs.
> I'm not totally clear on what you're saying. I believe you're pointing out
> that injecting hooks into the scripting environment a component runs in
> (such as by replacing methods on global protototypes) can allow the shadow
> root to be accessed even if no explicit access is given. I agree. This is
> not addressed with simple forms of Type 2 encapsutation. It is a non-goal
> for Type 2.

I'd like to understand what differentiates "simple forms of Type 2
encapsulation" from other potential forms that still meet the Type 2
criteria. Can you walk me through an example and show how they would be
used in a framework?

>  This is fraught.
> Calling something fraught is not an argument.

Good news! I provided an argument in the following sentence to help
contextualize my conclusion and, I had hoped, lead you to understand why
I'd said that.

> To get real ocap-style denial of access to the shadow DOM, we likely need
> to intercept and check all DOM accesses. Is the system still usable at this
> point? It's difficult to know. In either case, a system like caja *can*
> exist without explicit support....which raises the question: what's the
> goal? Is "Type 2" defined by real denial of access? Or is the request for a
> fig-leaf (perception of security)?
> Type 2 is not meant to be a security mechanism.

I'd like to see an example of Type 2 isolation before I agree to that.

> It is meant to be an encapsulation mechanism. Let me give a comparison.
> Many JavaScript programmers choose to use closures as a way to store
> private data for objects. That is an encapsulation mechanism. It is not, in
> itself, a hard security mechanism. If the caller can hook your global
> environment, and for example modify commonly used Object methods, then they
> may force a leak of your data.

A closure is an iron-clad isolation mechanism for object ownership with
regards to the closing-over function object. There's absolutely no
iteration of the closed-over state of a function object; any such
enumeration would be a security hole (as with the old Mozilla
object-as-param-to-eval bug). You can't get the value of "foo" in this
example except with the consent of the returned function:

var maybeVendFoo = function() {
  var foo = 1;
  return function(willMaybeCall) {
    if (/* some test */) { willMaybeCall(foo); }

Leakage via other methods can be locked down by the first code to run in an
environment (caja does this, and nothing prevents it from doing this for SD
as it can pre-process/filter scripts that might try to access internals).

Getting to closure-strength encapsulation means neutering all potential
DOM/CSS access. Maybe I'm dense, but that seems stronger than the "simple
form of Type 2".

If you're making the case that it might be helpful to folks trying to
implement Type 4 if the platform gave them a way to neuter access without
so much pre-processing/runtime-filtering, I could take that as an analog
with marking things non-configurable in ES. But it seems you think there's
an interim point that developers will use directly. I don't understand that
and would like to.

But that does not mean using closers for data hiding is a "fig-leaf" or
> "attractive nuisance".

Agreed, but only because they're stronger than you imply by analogy. What
I'm arguing is that if closures are the right analogy for some variant of
Shadow DOM then they'd need to get MUCH stronger  (Type 4) to meet that

> It's simply taking access to internals out of the toolset of common and
> convenient things, thereby reducing the chance of a caller inadvertently
> coming to depend on implementation details. ES6 private symbols serve a
> similar role.

Sadly, private symbols don't look likely to make an appearance in ES6.

> The proposal is merely to provide the same level of protection for the
> shadow DOM.
> This is the struggle I have with Type 2. I can get my mind around Type 4
> and want it very badly. So badly, in fact, that I bore most people I talk
> to with the idea of creating primitives that explain x-origin iframes (some
> sort of "renderer worker", how are the graphics contexts allocated and
> protected? what does it mean to navigate? what sorts of constraints can we
> put on data-propagation approaches for flowed layouts that can keep us out
> of security hell?).
> (1) The form of Type 1 encapsulation offered by current Shadow DOM specs
> cannot explain *any* built-in element that has a compound structure.
> Because built-in elements do not expose their Shadow DOM. It would be
> nearly impossible to do that and code them safely. If you want explanatory
> power for built-ins, Type 1 is not sufficient.

We agree on that.

> (2) Enabling iframes to be implemented as a custom element would be hard,
> and goes beyond the bare minimum of Type 4 requirements. That said, as far
> as I can tell there is no need whatsoever to expose the details of how
> graphics contexts are allocated to enable this. Why would you think that?

It's just where the archeology of trying to understand our one iron-clad
isolation mechanism (iframes) leads.

>  As I understand it, iframes are primarily about providing a security
> boundary with some tiny narrowly scoped holes, not about management of
> graphics resources. You would not use canvas-level primitives to implement
> iframes.
> What I don't understand is what daylight there can be, in practice,
> between Type 2 and Type 4-by-other-means. Either we lean on convention
> (using class names for styling) and see how it goes, potentially extracting
> something like the previously-proposed "::part()" system, or we go down the
> caja-style rabbit hole and try to lock down _all_ the things, and not just
> from incidental access.
> Where would you have us draw this line?
> I would draw the line between simple, obvious explicit mechanisms whose
> intended common use amounts to free-form access to the Shadow DOM, and
> mechanisms that indirectly allow this access by injecting traps into the
> global environment. Providing a clean global environment is not a goal for
> Type 2. Nor is a secure membrane for method calls.

I guess what I'm saying is that the slope from partial-encapsulation (your
type 2) to "real" encapsulation (type 4) is steep. If Type 2 looks like
it'll keep people out but doesn't, isn't the actual effort to doing so
isomorphic to building Type 4 on top of Type 1 (ala caja) or a very small
delta on top of it?

Until we can agree on this, Type 2 feels like an attractive nuisance
> I think you are only calling it an "attractive nuisance" because you did
> not understand what it is meant to provide, and instead believe it is a
> broken version of a different feature. It is not. I have tried to explain.
> I hope my explanation was informative.

I really am trying. Can you outline use-cases for this type of

> and, on reflection, one that I think we should punt to compilers like caja
> in the interim. If toolkits need it, I'd like to understand those use-cases
> from experience.
> Caja cannot solve the Type 2 or Type 4 use cases at all. Caja can be used
> by the embedder to protect the embedding page from content that it chooses
> to embed, by validating that it has been transpiled with Caja.

I'm using it as an analog for the technology that would be necessary to
build Type 4 on top of Type 1.

> But it cannot be used by an embedded component to protect itself from the
> embedding page. The component has no way to force the page to run all of
> its script through the Caja compiler, nor to verify that it has done so. If
> you think more about the security issues I expect it will be clear why it
> does not solve the problem.

Given that SD always exists in a scripting context with a shared heap,
shared globals, etc., I don't understand how mutual distrust is possible.
Iframes allow it and our story for needing strong encapsulation for SD has
always been "if you need that, put an iframe in your SD".

Which use-cases do you have which aren't satisfied by that solution?

Received on Friday, 14 February 2014 00:02:23 UTC