Html: What is the "security policy" for adding new events and elements to the Web Platform?

Created on 30 Oct 2020  Â·  5Comments  Â·  Source: whatwg/html

In whatwg/dom#831, there is a discussion about whether it is ok to add new html elements and/or attributes to the platform, if those additions could enable scripts to run. The issue/position put forth (e.g. here and here) is that it is possible for a site to configure an HTML sanitizer such that:

  1. Before the addition of the proposed new element/attribute, that sanitizer does not allow any known XSS vulnerabilities through the filter, but
  2. After the addition of the proposed new element/attribute, that sanitizer then suffers from a known XSS vulnerability.

If that situation is possible, then the conclusion (again, as presented here and here) is that we either must:

  1. Not add this feature to the web platform, or
  2. Provide a mitigation which prevents the vulnerability by default (e.g. through an enabling HTTP header)

If this is the "policy", it would seem to preclude several new features being proposed:

  1. Declarative custom elements
  2. Really, any new HTML element, assuming it wants to support the existing event listener content attributes. For example, new form elements from Open UI.
  3. Any new HTML events, assuming they would be accessible as a content attribute on existing elements.

This logically follows, since it is possible to construct a sanitizer that uses a deny-list, and constructs that deny list using only the element/attribute combinations available at a given point in time. Any new elements or attributes, even if they are "dangerous", would not be present in the deny list, and would therefore be allowed through this sanitizer.

Should this be the "policy" for the web platform?

One alternative viewpoint would be that we should instead work to guard against this situation:

  1. Before the addition of the proposed new element/attribute, well-configured, best-practices sanitizers do not allow any known XSS vulnerabilities through the filter, but

    1. After the addition of the proposed new element/attribute, these sanitizers then suffer from a known XSS vulnerability.

There are several comments on whatwg/dom#831 that appear to be supportive of this alternative way to think about risk mitigation (e.g. this, this, this, and (I think) this). The difficulty, of course, becomes defining "well configured" sanitizers. This is not an easy job, and likely requires some judgement calls to be made, and data to be gathered. A few categories of sanitizer could potentially be pre-defined as "not well configured", e.g. those using fixed deny-lists. While this "policy" is a bit harder to define, it does seem to re-open the possibility of adding new elements and attributes to the web platform.

Most helpful comment

IMO, it will be hard to have this discussion without more/better examples.

The policy being discussed, and which I attempted to articulate in the other thread about declarative shadow DOM, is simply stated: "ensure 100% backwards compatibility with any sanitizer that works today or could work today in principle, no matter how oddly constructed."

I think it's clearer when we give these things names, and I would propose to call this policy "No Sanitizer Left Behind," NSLB.

NSLB stands in contrast with another rule which I think is much closer to the rule we actually follow on the web: "ensure 100% backwards compatibility with any _reasonable_ sanitizer, and certainly with any sanitizer in widespread use today." Let's call that "No Good Sanitizer Left Behind," NGSLB, in opposition to NSLB.

In the declarative shadow DOM thread, I argued that <template shadowroot> runs afoul of NSLB and that <template onshadowroot> would/does, too.

On the other hand, NGSLB would probably allow <template onshadowroot>, and <template shadowroot> would probably be allowed, too.

I say "probably" because NGSLB requires us to look at actual _data_. What do real sanitizers actually _do?_ _Do_ they refuse to sanitize templates? _Do_ they strip all attributes starting with on, just to be safe, or is there a widespread sanitizer with a deny list? etc.

NSLB doesn't forbid as much as you'd think

In your statement at the top of this thread, you give three other examples of what you thought NSLB would forbid:

  1. Declarative custom elements
  2. Any new HTML element
  3. Any new HTML events

I don't think I agree with two of these examples. I think 2 would actually be _allowed_ under NSLB, and 1 might be as well; 3 would be forbidden, but that's probably good, actually.

New HTML Elements would be allowed under NSLB

I think new HTML elements are not strictly forbidden by NSLB, because HTMLUnknownElement exists. No sanitizer can be said to "work" today if it sanitizes only known, defined HTML elements, because it would be vulnerable on all modern browsers to attackers who made up a tag and attached an HTML event handler to it, e.g. <foo onmouseover="alert('xss')">foo</foo>. If the traditional behavior of browsers had been to leave unknown elements inert, _then_ a deny-list approach to sanitizing elements would work, but it absolutely doesn't work today, and so, at least in principle, we're allowed to introduce new HTML elements without violating NSLB, as long as it doesn't provide any _new_ vector for running scripts.

Declarative custom elements might be allowed, too… _without shadow DOM_

If you look at the explainer for declarative custom elements, it's basically just declarative shadow DOM wrapped in a new <definition> element. I see no way to use the <definition> element to run scripts except by virtue of the fact that the declarative shadow DOM _inside_ the <definition> element might be forbidden under NSLB.

Which is to say, declarative custom elements might well depend on declarative shadow DOM, and declarative shadow DOM in its currently spec'd implementation (<template shadowroot="open"><script>alert('ohai'')</script></template>) does seem to run afoul of NSLB, but that's just restating the original problem: declarative shadow DOM violates NSLB.

Declarative _custom elements_ don't violate NSLB except by using declarative shadow DOM, and if for some reason we thought it made sense to ship declarative custom elements _without_ declarative shadow DOM, I can foresee no _NSLB_ problems with that.

New HTML events (onBlah attributes) would be forbidden, and that's good, actually

As for forbidding any _new_ HTML events (onBlah attributes)… I think that might well be right. But, truth be told, I think _that_ is actually extremely reasonable. I think we should at the very least _hesitate_ before introducing any new HTML attribute (onBlah or otherwise) where the value of the attribute contains JavaScript that the browser will run.

If NSLB were officially the law of the land, and as a result there were a moratorium on new onBlah HTML attributes, I don't think we'd miss much, as long as it remained legal to use the _existing_ HTML attributes (onclick ,onkeydown, onpointermove, etc.)

As for Open UI specifically, it's hard to know in advance what specs Open UI will generate, but the only two proposals linked off of https://open-ui.org/ mention no _new_ event attribute names. <checkbox> would have change and input events… those both already exist. <select> includes change, click, and keydown events. Those all already exist, too. Those would all be legal under NSLB as a result.

Indeed, I'm not aware of anything on the Open UI list of form controls (breadcrumb, card, datepicker, slider, switch, table, tabs) that _would_ need a new onBlah attribute. I think we probably could forbid new onBlah attributes forever-ish, as long as the web continues to have the traditional keyboard + pointer interaction model it has today. (Maybe if/when it becomes possible to create and define VR objects in HTML, we can reopen this discussion…?)

But maybe HTML events prove that NSLB is wrong and NGSLB is right

NSLB asks us to "ensure 100% backwards compatibility with any sanitizer that works today or could work today in principle, no matter how oddly constructed."

But the web _has_ added new HTML events in recent years without a major international XSS incident. I believe (without proof) that no sanitizer in common use today uses a deny list for HTML events precisely _because_ it's just so obvious that new ones come along every day. Anyone who started with a deny list for HTML attributes and got screwed when we added onpointermove learned their lesson years ago!

In the declarative shadow DOM thread, it was suggested that perhaps <template onshadowroot> would/should be allowed, even if <template shadowroot> isn't. IMO, if anyone thinks creating new onBlah HTML attributes should be allowed, then they have, wittingly or not, left the path of NSLB and accepted NGSLB into their hearts.

I think we can probably live with NSLB. But maybe we shouldn't.

All 5 comments

IMO, it will be hard to have this discussion without more/better examples.

The policy being discussed, and which I attempted to articulate in the other thread about declarative shadow DOM, is simply stated: "ensure 100% backwards compatibility with any sanitizer that works today or could work today in principle, no matter how oddly constructed."

I think it's clearer when we give these things names, and I would propose to call this policy "No Sanitizer Left Behind," NSLB.

NSLB stands in contrast with another rule which I think is much closer to the rule we actually follow on the web: "ensure 100% backwards compatibility with any _reasonable_ sanitizer, and certainly with any sanitizer in widespread use today." Let's call that "No Good Sanitizer Left Behind," NGSLB, in opposition to NSLB.

In the declarative shadow DOM thread, I argued that <template shadowroot> runs afoul of NSLB and that <template onshadowroot> would/does, too.

On the other hand, NGSLB would probably allow <template onshadowroot>, and <template shadowroot> would probably be allowed, too.

I say "probably" because NGSLB requires us to look at actual _data_. What do real sanitizers actually _do?_ _Do_ they refuse to sanitize templates? _Do_ they strip all attributes starting with on, just to be safe, or is there a widespread sanitizer with a deny list? etc.

NSLB doesn't forbid as much as you'd think

In your statement at the top of this thread, you give three other examples of what you thought NSLB would forbid:

  1. Declarative custom elements
  2. Any new HTML element
  3. Any new HTML events

I don't think I agree with two of these examples. I think 2 would actually be _allowed_ under NSLB, and 1 might be as well; 3 would be forbidden, but that's probably good, actually.

New HTML Elements would be allowed under NSLB

I think new HTML elements are not strictly forbidden by NSLB, because HTMLUnknownElement exists. No sanitizer can be said to "work" today if it sanitizes only known, defined HTML elements, because it would be vulnerable on all modern browsers to attackers who made up a tag and attached an HTML event handler to it, e.g. <foo onmouseover="alert('xss')">foo</foo>. If the traditional behavior of browsers had been to leave unknown elements inert, _then_ a deny-list approach to sanitizing elements would work, but it absolutely doesn't work today, and so, at least in principle, we're allowed to introduce new HTML elements without violating NSLB, as long as it doesn't provide any _new_ vector for running scripts.

Declarative custom elements might be allowed, too… _without shadow DOM_

If you look at the explainer for declarative custom elements, it's basically just declarative shadow DOM wrapped in a new <definition> element. I see no way to use the <definition> element to run scripts except by virtue of the fact that the declarative shadow DOM _inside_ the <definition> element might be forbidden under NSLB.

Which is to say, declarative custom elements might well depend on declarative shadow DOM, and declarative shadow DOM in its currently spec'd implementation (<template shadowroot="open"><script>alert('ohai'')</script></template>) does seem to run afoul of NSLB, but that's just restating the original problem: declarative shadow DOM violates NSLB.

Declarative _custom elements_ don't violate NSLB except by using declarative shadow DOM, and if for some reason we thought it made sense to ship declarative custom elements _without_ declarative shadow DOM, I can foresee no _NSLB_ problems with that.

New HTML events (onBlah attributes) would be forbidden, and that's good, actually

As for forbidding any _new_ HTML events (onBlah attributes)… I think that might well be right. But, truth be told, I think _that_ is actually extremely reasonable. I think we should at the very least _hesitate_ before introducing any new HTML attribute (onBlah or otherwise) where the value of the attribute contains JavaScript that the browser will run.

If NSLB were officially the law of the land, and as a result there were a moratorium on new onBlah HTML attributes, I don't think we'd miss much, as long as it remained legal to use the _existing_ HTML attributes (onclick ,onkeydown, onpointermove, etc.)

As for Open UI specifically, it's hard to know in advance what specs Open UI will generate, but the only two proposals linked off of https://open-ui.org/ mention no _new_ event attribute names. <checkbox> would have change and input events… those both already exist. <select> includes change, click, and keydown events. Those all already exist, too. Those would all be legal under NSLB as a result.

Indeed, I'm not aware of anything on the Open UI list of form controls (breadcrumb, card, datepicker, slider, switch, table, tabs) that _would_ need a new onBlah attribute. I think we probably could forbid new onBlah attributes forever-ish, as long as the web continues to have the traditional keyboard + pointer interaction model it has today. (Maybe if/when it becomes possible to create and define VR objects in HTML, we can reopen this discussion…?)

But maybe HTML events prove that NSLB is wrong and NGSLB is right

NSLB asks us to "ensure 100% backwards compatibility with any sanitizer that works today or could work today in principle, no matter how oddly constructed."

But the web _has_ added new HTML events in recent years without a major international XSS incident. I believe (without proof) that no sanitizer in common use today uses a deny list for HTML events precisely _because_ it's just so obvious that new ones come along every day. Anyone who started with a deny list for HTML attributes and got screwed when we added onpointermove learned their lesson years ago!

In the declarative shadow DOM thread, it was suggested that perhaps <template onshadowroot> would/should be allowed, even if <template shadowroot> isn't. IMO, if anyone thinks creating new onBlah HTML attributes should be allowed, then they have, wittingly or not, left the path of NSLB and accepted NGSLB into their hearts.

I think we can probably live with NSLB. But maybe we shouldn't.

What is the "security policy" for adding new events and elements to the Web Platform?

Where there is a trade-off between new features and security:

From the side bench:

1. Outdated user agents must NOT be considered at all.

Reason: Otherwise there will not be stable progress.

Explanation: Existing obsoleteware is foremost the fault of the 4 big vendors as they don't force the software to be updated xor uninstalled (after a grace period of not updating such as 3 months) by default. Second to that it is the responsbility of the user. Example: If I use dual-wire-electricity it is not the fault of a lamp producer if I hurt myself in case the lamp comes with all the security feautres that are recent.

On forced updates XOR disables: This is tough especially on microsoft and apple as they are required to disable Internet Explorer / Edge and Safari on old versions, also on their mobile devices. There should be ways to re-enable (users should have control) but it should not be the default.

2. User privacy is the most relevant security feature and stands above all.

Reason: Users need to feel save and trust the platform, otherwise they will move to walled gardens and closed gateways (despite that there, tracking happens too, but it is out of reach of the users to even realize/decide).

Explanation: Evercookie, fingerprinting, cookies, retargeting, detection of user agents though hardware architecture etc. is NOT what users want. As at least one big vendor is big into ads, this policy will be hard to push through, yet the most important.

This feature is the most important and only diminished by outdated client side software (see rule 1).

3. New/added technology should not add new - more or less implementation independent - attack vectors.

Bad examples: This for instance has been ignored when introducing canvas, webgl and possibly webasm regarding fingerprinting

Thus if say shadow dom introduces such vectors, then it is a problem. I cannot judge if streaming shadow doms would do that, but in case it would, that's a problem (see rule 2).

4. Prevalent outdated server software should be considered but not prioritized.

Say outdated or badly written software (versions) such as load balancers, proxies, apache/nginx, php, fpm, node, wordpress, sanitizers should be considered but ultimately disregarded if there is no easy upgrade path respecting issues.

Reason: Web standards are not responsible for bad citizins. They are however responsible for making sure the technology itself is no threat to security (see rule 3). This for instance has been ignored when introducing canvas, webgl and possibly webasm.

@dfabulich thanks for the entertaining post, and the (better?) names for the two cases here. I agree with your points, mostly. You're right that new HTML elements, because of HTMLUnknownElement, should be ok to add. But new events, which come with "on*" content attributes, aren't. And as you rightly point out, we're adding new events all the time. I'm wondering if this issue has come up on the various threads discussing the APIs adding new events. (E.g. Picture-in-Picture, WebXR, Web Bluetooth, etc.) From a quick search, it doesn't look like this issue has been brought up at all elsewhere. But perhaps I missed it. If so, I'm wondering what the mitigation was.

It was probably clear from my OP, but I'm definitely in the NGSLB camp. Blocking forward progress on a purely-hypothetical situation seems like not the right trade off here. Of course, if there's a real issue on real sites today, let's make sure we address it.

Can the feature be used to bypass a safelist-based sanitizer (https://github.com/WICG/sanitizer-api might help making that concrete) is probably the bar, but it will also always depend. (Maybe this should move to whatwg/html?)

Can the feature be used to bypass a safelist-based sanitizer (https://github.com/WICG/sanitizer-api might help making that concrete) is probably the bar, but it will also always depend. (Maybe this should move to whatwg/html?)

I think I agree with that bar - safelist-based sanitizers should continue to be safe. And I believe they are here, as the "shadowroot" attribute will not be on existing safelists. The main "worry" on this thread seems to be denylist-based sanitizers, which don't seem to be future proof or secure on their own.

I agree that this should probably be on whatwg/html - I don't think I have permission to move it. Do you?

Was this page helpful?
0 / 5 - 0 ratings