Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Chris Wilson 100 posts 377 karma points
    Oct 04, 2016 @ 11:16
    Chris Wilson
    0

    Scripts.cshtml violates strict Content-Security-Policy script-src directives

    Background

    We're currently seeking to implement strict CSPs on all sites we operate; as part of this we are setting the following (abridged) directives:

    default-src: none;
    script-src: 'self';
    style-src: 'self';
    upgrade-insecure-requests;
    

    As a result, we must remove all scripts that require the directives 'unsafe-inline' and 'unsafe-eval'.

    Work so far

    In my own code I have switched to using JSON APIs to get .NET data into scripts - rather than building the scripts with Razor code - however the Umbraco Forms file, Scripts.cshtml, is proving somewhat more difficult.

    The first issue arises when the contourDateFormat variable is set:

    <script type="text/javascript">
        var contourDateFormat = "@Html.ConvertDateFormat()";
    </script>
    

    I resolved this by setting the value on a hidden field, then moving the above line of code into a JavaScript file and retrieving the value with jQuery:

    var contourDateFormat = $("#h_DateFormat").val();
    

    Due to the fact that the variable set previously was global, this seems to work well.

    The Issue

    The issue arises when attempting to fix the inline script which takes a FormClientId:

    <script>
        (function ($, formId) {
            // Script body here
        }(jQuery, '@Model.FormClientId'));
    </script>
    

    I can replicate the above fix with this code, but this produces issues on pages that contain multiple forms.

    Has anyone else come across this issue, or can think of a possible solution to this specific aspect?

    Kind Regards,

    Chris

  • Chris Wilson 100 posts 377 karma points
    Oct 04, 2016 @ 15:22
    Chris Wilson
    0

    Rightio; I'm working through a workaround and I'd appreciate someone checking I don't have a glaring hole in my logic as JavaScript is not usually my forte.

    First I have taken the following inline script from Scripts.cshtml:

    <script>
        (function ($, formId) {
           // Do work
        }(jQuery, '@Model.FormClientId'));
    </script>
    

    and refactored it into a JavaScript file which calls an API:

    $.get("/umbraco/Surface/Global/GetNextFormId/", function (model) {
        if (model != null) {
            (function ($, formId) {
                // Do work
            }(jQuery, model));
        }
    });
    

    Inside Scripts.cshtml I have added the following:

     TempData["formsList"] = TempData["umbracoForms"];
    

    Then inside my Global controller I have added the following action:

    [HttpGet]
    public string GetNextFormId()
    {
        var formsList = TempData["formsList"] as List<Guid>;
        if (formsList != null && formsList.Any())
        {
            var formId = formsList.First();
            formsList.Remove(formId);
            TempData["formsList"] = formsList;
    
            return formId.ToString().Replace("-", "");;
        }
    
        return string.Empty;
    }
    

    So long as you're calling @Umbraco.RenderMacro("umbracoformsRenderScripts") yourself at the bottom of the page, and the hidden fields have been rendered before the script is executed, this approach seems to work - as unsatisfyingly hacky as it is.

    I'm going to be testing this heavily, but if anyone can spot any glaring errors as to why this shouldn't work (at least until the Umbraco Forms team release an official solution), I'd really appreciate that!!

    Cheers,

    /Chris.

Please Sign in or register to post replies

Write your reply to:

Draft