Safely injecting HTML into a Polymer template


In a custom element, I try to replace an item’s body text with HTML for line breaks and links. It was working when I just handled line breaks (nl2br()), but no longer when handling links (linkify()).

  get formattedBody {
    if (item.isEmpty) return 'Loading...';
    return "${InputFormatter.nl2br(InputFormatter.linkify(item['body']))}";

  itemChanged() {
    // Trick to respect line breaks.
    HtmlElement body = $['body'];
    body.innerHtml = formattedBody;

I get a warm and safe security message e.g.:

Removing disallowed attribute <A href="">

I also tried setInnerHtml(), to no avail.

Ideas? Thank you!


I’ve got a <safe-html> element working. Verified on Chrome and even post-dart2js on Safari. Vote up this answer if you’d like me to turn it into a lib available on


<safe-html validator="{{nodeValidator}}">{{someHtml}}</safe-html>

(Passing in your own validator is optional. Without it, we’ll use a default.)


<link rel="import" href="../../../../../../../packages/polymer/polymer.html">
<polymer-element name="safe-html">
    <div id="container"></div>

  <script type="application/dart" src='safe_html.dart'></script>


library safe_html;

import 'dart:async';
import "dart:html";

import "package:polymer/polymer.dart";

class SafeHtml extends PolymerElement  {
  @published NodeValidator validator = new NodeValidatorBuilder()
    ..allowHtml5(uriPolicy: new DefaultUriPolicy());

  SafeHtml.created() : super.created();

  addFragment() {
    DivElement container = $['container'];
    String fragment =  this.text;
    container.setInnerHtml(fragment, // Set the fragment in a safe way.
      validator: validator);
    this.text = ""; // Clear the original fragment passed to the element.

  attached() {

class DefaultUriPolicy implements UriPolicy {

  // Allow all external, absolute URLs.
  RegExp regex = new RegExp(r'(?:http://|https://|//)?.*');

  bool allowsUri(String uri) {
    return regex.hasMatch(uri);

If you choose to pass your own NodeValidator, do it by specifying a getter in the parent element that uses <safe-html>:

NodeValidator get nodeValidator => new NodeValidatorBuilder()
..allowHtml5(uriPolicy: new ItemUrlPolicy());

As you can see I reference a UriPolicy which I keep in a separate file like uri_policy.dart:

import 'dart:html';

class ItemUrlPolicy implements UriPolicy {

  RegExp regex = new RegExp(r'(?:http://|https://|//)?.*');

  bool allowsUri(String uri) {
    return regex.hasMatch(uri);

With lots of help from Günter Zöchbauer and the authors of other helpful posts on SO.

Answered By – David Notik

Answer Checked By – Mary Flores (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *