且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JQuery 3.5.1 拒绝执行内联脚本,因为它违反了以下内容安全策略指令:

更新时间:2022-10-19 18:56:15

基于我的相关问题 此处此处 我想我必须为 jQuery 3.1+ 添加 script-src unsafe-inline 才能在以下场景中正常工作

1>您使用的是 jQuery 3.1+
2>jQuery 被添加到_layout 页面或主页,所以它在开始时只加载一次.
3>您正在使用 AJAX 加载部分内容.

nonce 方法中,建议为每个http 请求使用唯一的nonce.但他的方法在这里行不通.因为 AJAX 调用将在标头中获得不同的随机数.所以之后的任何 jQuery 调用都不起作用.

对我来说它使用 2.1.1 因为 jQuery 2.x 解析所有 <script>...</script>HTML 中的标签并将其放入动态生成的脚本标签中或通过 eval( ) 执行这些标签 详细信息 我有 script-src nonce-xyz unsafe-eval

I upgraded jQuery from 2.1.1 to 3.5.1 and I started seeing this issue with jQuery

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-YURLOAQRrIwdGEqYSSpHx9YSWDM......' 'unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-2mvMk0Nvn96VqS1UEmAZSVSEkK0CkPN....'), or a nonce ('nonce-...') is required to enable inline execution.

I do not want to use 'unsafe-inline'.

The issue is documented here , here and here in 2017-2018. I thought the issue is resolved by now in jQuery 3.5.1 unless I am missing something.

My application is developed in .NET Core 5.

Index.cshtml

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <script src="~/lib/jquery/3.5.1/jquery.min.js" asp-add-nonce="true"></script>
</head>
<body>
    
    <button type="button" id="btnGetContent">Get Content</button>

    <div id="result">
        <partial name="_Test" />
    </div>    

    <script src="~/js/index.js"></script>

</body>
</html>

_Test.cshtml Partial View

@System.DateTime.Now.ToString();

<script type="text/javascript" asp-add-nonce="true">    
   // partial view specific inline script
</script>

index.js

$(function () {

    $("#btnGetContent").click(function () {
        $.ajax({
            type: "GET",            
            url: "/test/getcontent",            
            processData: true,
            cache: false
        })
        .done(function (response, textStatus, jqXHR) {
            // in browser's console I notice the error at this line
            $("#result").html(response);
        })          
    })   
})

Controller

public class TestController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [HttpGet]
    public IActionResult GetContent()
    {
        return PartialView("_Test");
    }
}

CSP policy

"default-src 'none'; script-src 'self' 'nonce-{0}' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; child-src 'self';"

I have custom asp-add-nonce tag helper and a nonce middleware. ** For each request ** the tag helper and the middleware inject new nonce value into script tag and CSP policy respectively, and this has been working fine.

After I upgraded jQuery to 3.5.1, looks like jQuery also need nonce value in script tag so I have added asp-add-nonce="true" in header like
<script src="~/lib/jquery/3.5.1/jquery.min.js" asp-add-nonce="true"></script>

ISSUE
I think the issue here, Since nonce value is created for each http request, and jQuery is loaded only once per page. Get Content request creates new value which of-course does not match with original value that was injected in jQuery script tag. So we get error Refused to execute inline script...

Is there anyway to resolve this without adding nonce to jQuery's script tag?

UPDATE 1
After looking the CSP report submitted by browser, it reveled more details. The violated directive is actually script-src-elem. My CSP policy does not even have that directive. This directive is available in CSP 3 version. Not sure why browser is erroring out on jQuery for this directive.

UPDATE 2
You can download repository to re-produce the issue

Well based on my related Questions here and here I think I will have to add script-src unsafe-inline for jQuery 3.1+ to work properly in the following scenario

1>You are using jQuery 3.1+
2>jQuery is added on _layout page or main page so it load only once at start.
3>You are loading partial content using AJAX.

In nonce approach it is recommended to use unique nonce for each http request. But his approach will not work here. Because AJAX call will get different nonce in header. So any jQuery call after will not work.

For me it was working with 2.1.1 because jQuery 2.x parses all <script>...</script> tags from the HTML and puts it in a dynamically generated script tag or executes those through eval( ) details and I had script-src nonce-xyz unsafe-eval