1
votes

How do I avoid Telerik KendoUI creating inline scripts when using ASP.NET MVC Kendo compontents?

The reason for avoiding inline scripts is to adhere by CSP header

Content-Security-Policy: script-src 'self' 'unsafe-eval' https://kendo.cdn.telerik.com

And not to get errors like

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval' https://kendo.cdn.telerik.com".

Is there a way to remove the kendo generated inline scripts or attach Content Security Policy nonce / sha256 to the scripts?

Simple Example (KendoUI Menu)

cshtml

@(Html.Kendo().Menu()
  .Name("nav-menu")
  .Items(items =>
  {
      items.Add().Text("Home").Action("Index", "Overview");
  })
)

Browser html

<ul class="k-widget k-reset k-header k-menu k-menu-horizontal" id="nav-menu" data-role="menu" tabindex="0" role="menubar" aria-activedescendant="nav-menu_mn_active">
    <li class="k-item k-state-highlight k-state-default k-first" role="menuitem">
        <a class="k-link" href="/">Home</a>        
    </li>
</ul>
<script>
    jQuery(function(){jQuery("#nav-menu").kendoMenu({});});
</script>

Solution

After the answer from @dimodi I ended up using nonce on kendo deferred initialization scripts.

Source: CSP Nonces in ASP.NET

cshtml

@(Html.Kendo().Menu()
  .Name("nav-menu")
  .Items(items =>
  {
      items.Add().Text("Home").Action("Index", "Overview");
  })
  .Deferred()
)

<script type="text/javascript" nonce="@Html.ScriptNonce()">
    @Html.Kendo().DeferredScripts(false)
</script>

Startup.cs

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use((context, next) =>
        {
            var rng = new RNGCryptoServiceProvider();
            var nonceBytes = new byte[32];
            rng.GetBytes(nonceBytes);
            var nonce = Convert.ToBase64String(nonceBytes);
            context.Set("ScriptNonce", nonce);
            context.Response.Headers.Add("Content-Security-Policy",
                new[] {$"script-src 'self' 'unsafe-eval' https://kendo.cdn.telerik.com 'nonce-{nonce}';"
            });
            return next();
        });
    }
}

public static class NonceHelper
{
    public static IHtmlString ScriptNonce(this HtmlHelper helper)
    {
        var owinContext = helper.ViewContext.HttpContext.GetOwinContext();
        return new HtmlString(owinContext.Get<string>("ScriptNonce"));
    }
}
3

3 Answers

0
votes

You can control where the Kendo UI MVC inline scripts are rendered on the page, but cannot completely remove them. Actually, you can, but then the widgets will not initialize.

Consider using the non-MVC Kendo UI widgets:

http://docs.telerik.com/kendo-ui/aspnet-mvc/kendo-ui-vs-mvc-wrappers

Vanilla HTML/JavaScript Kendo UI widgets provide full control over the placement of the initialization scripts - server wrappers render the widgets' initialization scripts right after the widget's HTML output. Even if you use deferred initialization, the scripts are still kept in the View. When using plain (non-wrapper) Kendo UI widgets, you write the initialization scripts yourself and can move them to external script files.

Also keep in mind that Kendo UI templates rely on eval, which will also bring troubles if CSP is enabled.

0
votes

I tried using the NWebSec CSP package from Nuget (5.1.1 https://docs.nwebsec.com/en/aspnet4/index.html) but could not get it to work with the NWebSec '<'content-Security-Policy> section in Web.config. Even though the CSP looked fine in report-only mode and Kendo Widgets work, as soon as you turn on the CSP, the Widgets fail completely.

I remarked out the '<'content-Security-Policy> section of the '<'nwebsec> in Web.config and moved all of my CSP directives back into '<'httpProtocol> <'customHeaders> and Kendo MVC (2018.1.322) now works.

By maintaining NWebSec as part of the project and adding @using NWebsec.Mvc.HttpHeaders.Csp into Views and applying the HTMLHelper into script tags I get an automatically generated nonce for any inline scripts '<'script @Html.CspScriptNonce() > so it is still valuable to keep NWebSec

0
votes

For anyone searching this in 2019, we use Joonasw.AspNetCore.SecurityHeaders for our Csp and it was blocking eval() that kendo used, we solved this by adding this to our Startup

app.UseCsp(csp =>
            {
                 ...
                   csp.AllowScripts
                .FromSelf()
                .From("kendo.cdn.telerik.com")
                .AllowUnsafeInline()
                .AllowUnsafeEval();

                 ...
             }