Secure composition of custom elements

# Mike Samuel (a day ago)

I've been looking into the security of webcomponents frameworks. This might be of interest to framework developers and spec authors.

Problem

  [{{ $text }}]({{ $uri }})

In a traditional template system, if $text is a crafted input like <script>alert(1)</script> then unintended code execution occurs.

Webcomponents frameworks don't suffer from this because the HTML parser does not receive the payload, but when $uri is javascript:alert(1), the attacker controlled value reaches the URI parser, and from there the JS interpreter.

Traditional frameworks can address this by autoescaping [1] -- building in knowledge of the 100+ elements and similar number of attributes with special semantics to insert escaping directives.

  [{{ $text }}]({{ $uri }})

=> automagic happens =>

  [{{ $text |escapeHtml }}]({{ $uri |checkSafeUrl |escapeHtml }})

Well-trained code reviewers & security auditors might suggest the same where auto-escaping is not an option.

That does not work for custom elements. Consider that

<dom-module id="foo-element"><template>
  [{{ $text }}]({{ $uri }})
</template></dom-module>

defines a <foo-element>. It is simple enough that it can be similarly

checked by human reviewers or tweaked by compiler passes.

But add

<dom-module id="bar-element"><template>
  <foo-element url="{{ $url }}" text="Hello, World!"></foo-element>
</template></dom-module>

and the picture is less clear.

An alert human reviewer might infer that a third-party value reaching $url is a problem, but the vulnerability is indirect, so more mistakes may result. An auto-escaping pass could insert escaping directives if it stands in a place to do whole program analysis. CSP, browser XSS heuristics, etc. are equally effective, but it would be nice to have defense in depth.

The definition of <foo-element> is vulnerable because it uses an <a> element.

If instead, $url reached javascript that used a sandboxed iframe or window.open, then it would not be vulnerable in the same way.

The vulnerability is due to an implementation detail that users of

<foo-element> should not need to worry about. Application developers

and code reviewers should not bear the responsibility for keeping attacker controlled values away from the link element that underlies

<foo-element>.

Introducing Polymer-resin [2]

Polymer resin hooks into polymer to vet the results of data binding expressions just before they reach an IDL bound property.

Safe HTML types [3] allow a (runtime) type-safe way of avoiding false positives.

[1] developers.google.com/closure/templates/docs/security#autoescaping [2] Polymer/polymer-resin [3] google/safe-html-types/blob/master/doc/index.md [4] slides: goo.gl/Nopoye

I'm most familiar with Polymer and would love to hear about what other frameworks are doing to deal with this issue.

Contact us to advertise here

Want more features?

Request early access to our private beta of readable email premium.