Secure way of inserting dynamic values in external JavaScript files

前端 未结 1 1008
独厮守ぢ
独厮守ぢ 2020-12-06 17:30

I\'m implementing Content Security Policy headers using the following policy

Content-Security-Policy: default-src \'self\'

so will need to avoid

相关标签:
1条回答
  • 2020-12-06 18:18

    $('#@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)')

    Yeah this isn't a good approach in general. Razor will HTML-escape by default but the context isn't simply HTML here, it's:

    • an identifier, inside
    • a CSS selector, inside
    • a JavaScript string literal, inside
    • a JavaScript statement, inside
    • an HTML CDATA element (<script>)

    so just HTML-escaping is the wrong thing - any characters that are special in the context of selectors or JS string literals (such as dot, backslash, apostrophe, line separators...) would break this statement.

    Maybe that's not super-important for this specific example, assuming the result of GetFullHtmlFieldName is always going to be something safe, but that's not a good assumption for the general case.

    C# Generated JavaScript: a bit clunky and it kind of defeats some of the advantages of using a CSP

    Agreed, avoid this. Getting the caching right and transferring the information from the ASP that generates the page content to the page that generates the script is typically a pain.

    Also generating JavaScript is not necessarily that simple. ASP and Razor templates don't give you an automatic JS escaper. JSON encoding nearly does it, except for the niggling differences between JSON and JS (ie U+2028 and U+2029).

    Hidden Form Fields

    More generally, putting the information in the DOM. Hidden form fields are one way to do this; data- attributes are another commonly-used one. Either way I strongly prefer the DOM approach.

    When using hidden form fields you should probably remove the name attribute as if they're inside a real <form> you typically don't actually want to submit the data you were passing into JS.

    This way you can inject the content into the template using normal default-on HTML escaping. If you need more structure you can always JSON-encode the data to be passed. jQuery's data() helper will automatically JSON.parse them for you too in that case.

    <body data-mcefields="@Json.Encode(GetListOfHtmlFields())">
    ...
    var mce_array = $('body').data('mcefields');
    $.each(mce_array, function() {
        var element = document.getElementById(this);
        $(element).tinymce({ ... });
    });
    

    (Although... for the specific case of selecting elements to apply an HTML editor to, perhaps the simpler way would be just to use class="tinymce" and apply with $('.tinymce').tinymce(...)?)

    0 讨论(0)
提交回复
热议问题