17

I'm using polymer-jsonp to perform JSONP requests, but the response sometimes contains html.

For example, supposing that post.content is "<strong>Foo</strong> bar", how can I display {{post.content}} such that "Foo" is in bold?

<polymer-element name="feed-element" attributes="">
  <template>
    <template repeat="{{post in posts.feed.entry}}">
      <p>{{post.content}}</p>
    </template>
    <polymer-jsonp url="url" response="{{posts}}"></polymer-jsonp>
  </template>
  <script>
    Polymer('feed-element', {
      created: function() { },
      attached: function() { },
      detached: function() { },
      attributeChanged: function(attrName, oldVal, newVal) { }
    });
  </script>
</polymer-element>
Peter Burns
  • 44,401
  • 7
  • 38
  • 56
Tachun Lin
  • 942
  • 3
  • 11
  • 18

3 Answers3

14

Polymer will not stamp unescaped HTML via data-binding because it becomes a vulnerability for XSS attacks.

There are talks ongoing about making it possible to stamp HTML under limited circumstance, or to allow for customized filtering, but this is not implemented yet at the data layer.

It is possible to do what you want today using an additional custom element, but again, be advised of the potential for bad things to happen if you render untrusted HTML into your page.

Here is an example that shows this technique:

http://jsbin.com/durajiwo/1/edit

Scott Miles
  • 11,025
  • 27
  • 32
  • 3
    Example of Scott's technique using Flickr's jsonp API and ``: http://jsbin.com/zoduhoqu/1/edit – ebidel Mar 06 '14 at 00:30
  • Is juicy-html also vulnerable to XSS attacks ? I guess the answer is positive, but just checking – saurshaz Jan 10 '15 at 06:14
  • @Scott, could you comment more on the need for additional element for this to work? – user1463822 Jan 28 '15 at 12:19
  • You don't *need* to have an additional element. You can always just do `this.innerHTML = ...`. The idea is that we cannot allow you to directly bind data to HTML, without you doing _something_ to explicitly enter in to the danger zone. Some folks use preprocessors that attempt to explicitly forbid `innerHTML`, other teams require input sanitizers. There are a variety of solutions, and we can improve in this area. – Scott Miles Jan 29 '15 at 20:48
9

For those look for polymer 1.0

<dom-module id="html-echo">
  <style>
    :host {
      display: block;
    }
  </style>
  <template>
  </template>
</dom-module>

<script>
  (function () {
    Polymer({
      is: 'html-echo',
      properties: {
        html: {
          type: String,
          observer: '_htmlChanged'
        }
      },
      _htmlChanged: function (neo) {
        // WARNING: potential XSS vulnerability if `html` comes from an untrusted source
        this.innerHTML = neo;
      }
    });
  })();
</script>
wener
  • 7,191
  • 6
  • 54
  • 78
  • Bear in mind, since binding is statically calculated at pre-render time, your imperative declarations like `[[foo]]` or `{{bar}}` will not work in your new html since they're added post render. – AP. Apr 26 '16 at 16:04
  • how we can call post render in this method ? – S. Ali Mihandoost Aug 14 '16 at 10:14
  • `this.innerHTML = postProcess(neo);` does this fit for you ?@Ali.MD – wener Aug 15 '16 at 08:45
  • I think in Polymer 1.0 the – codeMonkey Oct 01 '16 at 17:38
2

If you're sure it is what you want to do, just use innerHTML.

_renderHtml: function(html) {
  this.$.dynamicHtmlContainer.innerHTML = html;
}

Or to dynamically add a shadow-dom child:

_renderHtml: function(html) {
  var div = document.createElement('div');
  div.innerHTML = html;
  Polymer.dom(this).appendChild(div);
}

I think Polymer.dom is being removed in Polymer 2.0 though.

Jacob Phillips
  • 8,841
  • 3
  • 51
  • 66