9

In underscore.js, template rendering causes violation of the 'unsafe-eval' property, with CSP error at following line:

render = new Function(settings.variable || 'obj', '_', source);

The solution to this on some forums have been to Sandbox the underscore according to the Chrome documentation.

But how will this solution work for a web based application where there are number of users with different browsers? Are there any alternate solutions to this problem? Please note that the application I am working on is large and heavy, so code changing will take a lot of time.

  • 3
    Yeah, creating a new function dynamically is the same as eval so blocked by CSP. I don't think there's a way around this. I've not used underscore.js before, but I've read that other templating libraries allow you to precompile the template, and this is the only way around it, but this may not work for you. – Rik Lewis Feb 22 '17 at 12:19
2

From html5rocks, set the nonce in the Content-Security-Policy header:

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

Place the nonce somewhere on your page:

...
<body data-nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
...

Call the function below with the nonce value in question before you start using underscore in your scripts.

function handleFnNonceRequirement(nonce) {
    window.Function = function () {
        var renderNode = document.createElement("script"),
            len = arguments.length,
            source = arguments[len-1],
            args = [];

        if ( 1 < len ) {
            for ( var i=0; i<(len-1); i++ ) {
                args.push(arguments[i]);
            }
        }

        renderNode.text = "function __ifYouAbsolutelyMustUseIt() { return function("+args.join(", ")+") {" + source + "}}";
        renderNode.setAttribute('nonce', nonce);

        document.head.appendChild(renderNode).parentNode.removeChild(renderNode);
        return __ifYouAbsolutelyMustUseIt();
    };
}

handleFnNonceRequirement(document.getElementsByTagName("BODY")[0].getAttribute('data-nonce'));

Hope there is a better way than this.

  • Using nonce does work, but as you mentioned it may not be the most efficient way. For this project, I ended up character escaping on the client and server side. I updated the source code for Jabbered component to accommodate character escaping and using escape function in backbone.js to solve the issue. – hshantanu Dec 4 '18 at 15:25
0

The solution suggested by @Sand worked for me. However, to make the entire thing more self-contained so that I could place the code in multiple pages easily, I get the nonce from the script element itself.

<script type="text/javascript" id="noncense" nonce="...">
   function handleFnNonceRequirement(nonce) {
    .
    .
    .
   }
   handleFnNonceRequirement($("#noncense")[0].nonce);
</script>

If there's an issue with this approach let me know.

  • Using nonce does work, but I feel it may not be the most efficient way. For this project, I ended up character escaping on the client and server side. I updated the source code for Jabbered component to accommodate character escaping and using escape function in backbone.js to solve the issue. – hshantanu Dec 4 '18 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.