14

The Chrome API's Manifest version 2 has removed the ability to do unsafe-eval. This means using the eval function or in general dynamically creating a function from text.

It seems like most if not all Javascript Templating Engines do this. I was using Jaml, but I tried several others like backbone.js (which really uses underscore.js's templating engine) with no luck.

This comment on the Chromium project seems to indicate that there are a great many libraries that suffer from this.

I think Angular.js has a CSP-safe mode, but Angular.js is really too big for what we need. We just need a fairly basic templating engine and don't need models or controllers and such. Does anyone know about any CSP-compatbility templating engines out there?

blahdiblah
  • 33,069
  • 21
  • 98
  • 152
Thariq Shihipar
  • 1,072
  • 1
  • 12
  • 27
  • 1
    Duplicate? http://stackoverflow.com/questions/10744764/javascript-template-library-that-doest-use-eval-new-function – apsillers Jul 16 '12 at 13:31

2 Answers2

8

The best solution to this problem is to pre-compile your templates before you deploy your extension. Both handlebarsjs and eco offer pre-compilation as a feature. I actually wrote a blog post that goes into more depth.

Matthew
  • 12,892
  • 6
  • 42
  • 45
4

You should absolutely use precompilation as recommended by Mathew for medium and big templates. For extremely small templates we are using this:

var template = function(message, data) {
  if (typeof data === 'undefined') {
    return _.partial(template, message);
  } else {
    return message.replace(/\{\{([^}]+)}}/g, function(s, match) {
      var result = data;
      _.each(match.trim().split('.'), function(propertyName) {
        result = result[propertyName]
      });
      return _.escape(result);
    });
  }
};

var data = {
  foo: 'Hello',
  bar: { baz: 'world!' }
};

// print on-the-fly
template('{{foo}}, {{bar.baz}}' args); // -> 'Hello, world!'

// prepare template to invoke later
var pt = template('{{foo}}, {{bar.baz}}');
pt(args); // -> 'Hello, world!'

This implementation does not use eval, but it will require underscore.

Nacho Coloma
  • 7,070
  • 2
  • 40
  • 43
  • Underscore internally uses the `Function` constructor to compile the template, which is implicit `eval`. See https://github.com/jashkenas/underscore/blob/91632707/underscore.js#L1192-L1232 – Rob W Dec 12 '13 at 13:39
  • 1
    This implementation does not use the `_.template` method, which has the `eval` dependency (other underscore methods are fine). We are using it with a Content-Security-Policy and works nicely. – Nacho Coloma Dec 12 '13 at 16:23
  • Sorry, I misunderstood your last remark. I mistakenly interpreted it as "underscore's `_.template` does not use eval". You're absolutely correct: Your proposed implementation does not use `eval`. – Rob W Dec 12 '13 at 16:25