jQuery 3.1.1 违反 CSP 指令 [英] jQuery 3.1.1 violation of CSP directive

查看:21
本文介绍了jQuery 3.1.1 违反 CSP 指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 jQuery 3.1.1 版,并且正在尝试实施 内容安全政策 (CSP) 指令在我的网页上.

I'm using jQuery version 3.1.1 and I'm trying to implement Content Security Policy (CSP) directives on my webpage.

我收到以下错误:

拒绝执行内联脚本,因为它违反了以下内容内容安全策略指令:"script-src 'self''nonce-c20t41c7-73c6-4bf9-fde8-24a7b35t5f71'".无论是'unsafe-inline' 关键字,一个散列('sha256-KAcpKskREkEQf5B3mhDTonpPg34XnzaUC5IoBrOUrwY='),或随机数('nonce-...') 是启用内联执行所必需的.

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-c20t41c7-73c6-4bf9-fde8-24a7b35t5f71'". Either the 'unsafe-inline' keyword, a hash ('sha256-KAcpKskREkEQf5B3mhDTonpPg34XnzaUC5IoBrOUrwY='), or a nonce ('nonce-...') is required to enable inline execution.

错误是在主 jquery.js 脚本文件的第 82 行产生的.这一行的内容是:

The error is produced on line 82 of the main jquery.js script file. The content of this line is:

doc.head.appendChild( script ).parentNode.removeChild( script );

基本上,它向 DOM 添加了一个内联脚本标记,这违反了 CSP.

Basically, it adds an inline script tag to the DOM, that violates the CSP.

我不想使用'unsafe-inline'.还有其他方法可以规避这个错误吗?

I do not want to use 'unsafe-inline'. Is there another way to circumvent this error?

正如您在 CSP 违规中看到的那样,我使用的是 CSP 级别 2(随机数),但它被忽略了.是否可以(以某种方式)在附加脚本标记时通知 jQuery 使用此随机数?

As you can see on the CSP violation, I'm using CSP level 2 (nonce), but it is ignored. Would it be possible (somehow) to inform jQuery to use this nonce when appending the script tag?

这是 HTML 的样子(使用 Express.js 模板用于随机数)

This is how the HTML looks like (using an Express.js template for nonce)

<script nonce="<%=nonce%>" type="text/javascript" src="jquery.js"></script>

HTML 渲染后,脚本标签上的 nonce 属性与服务器发送的 CSP nonce 指令匹配.

Once the HTML is rendered, the nonce attribute on the script tag matches the CSP nonce directive sent by the server.

它确实适用于纯 JavaScript:

It does work with plain JavaScript:

<script nonce="<%=nonce%>" type="text/javascript">
        var userEmail = "<%=user.user.email%>";
</script>

如果没有 nonce 属性,这个脚本标签将违反 CSP 指令.

Without the nonce attribute, this script tag would violate the CSP directive.

推荐答案

它看起来像是 jQuery 的一个错误或怪癖,它附加内联脚本的方式最终会丢弃它们的所有属性,我看不到明显的修复方法为了测试它,我使用了以下 HTML:

It looks like a bug or quirk of jQuery how it appends inline scripts ends up discarding all of their attributes and I can't see an obvious way of fixing it to test it I used the following HTML:

<!DOCTYPE html>
<html>

    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src http://localhost 'nonce-123456' ; child-src 'none'; object-src 'none'; script-src 'nonce-123456';">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js" nonce="123456"></script> <!-- HTML nonce works -->
        <script nonce="123456">
            // This works
            console.log('Inline nonce works');

            // This will also work
            var s = document.createElement('script');
            s.setAttribute('nonce', '123456');
            s.textContent = 'console.log("Dynamically generated inline tag works")';
            document.head.appendChild(s);

            // This won't work
            var s2 = document.createElement('script');
            s2.setAttribute('nonce', '123456');
            s2.textContent = 'console.log("Dynamically generated inline tag appended via jQuery doesn\'t work")';
            $(document.head).append(s2); // This will throw a CSP error
        </script>
    </head>

<body>

</body>

</html>

使用 jQuery append 时会经历以下过程(减少一点):

When using jQuery to append it goes through the following process (reduced a little):

  • 创建一个文档片段并向其附加一个脚本标签
  • type=false/" 属性应用于脚本标记
  • 移除 type 属性
  • 如果存在 src 属性,它会通过 Ajax 检索脚本(没有进一步调查)
  • 如果不是,则运行 DOMEval(node.textContent.replace(rcleanScript, ""), doc)
  • Creates a document fragment and appends a script tag to it
  • Applies a type="false/" attribute to the script tag
  • Removes the type attribute
  • If a src attribute is present it retrieves the script via Ajax (didn't investigate this further)
  • If not it runs DOMEval(node.textContent.replace(rcleanScript, ""), doc)

DomEval 看起来像这样(添加了注释):

DomEval looks like this (with added comments):

doc = doc || document;
var script = doc.createElement( "script" );
script.textContent = code;
doc.head.appendChild( script ).parentNode.removeChild( script );

如您所见,在追加之前,没有任何属性会转移到新元素,因此 CSP 失败.

As you can see, no attributes would carry over to the new element before it was appended and as such CSP fails.

解决方案是仅使用原生 JavaScript 来附加元素而不是 jQuery,或者可能等待错误修复/对您的报告的响应.我不确定他们以这种方式为内联脚本标签排除属性的理由是什么,这可能是一种安全功能?

The solution would be to just use native JavaScript to append the element as opposed to jQuery or possibly wait on a bug fix/response to your report. I'm unsure what their reasoning would be to exclude attributes in this manner for inline script tags maybe a security feature?

以下应该可以在没有 jQuery 的情况下实现您想要的 - 只需将 textContent 属性设置为您的 JavaScript 源代码.

The following should achieve what you want without jQuery - just set the textContent attribute to your JavaScript source code.

var script = document.createElement('script');
script.setAttribute('nonce', '<%=nonce%>');
script.textContent = '// Code here';
document.head.appendChild(script);

因此,该特定行抛出错误的根本原因是附加的标签实际上是一个具有相同代码的新标签,并且没有应用任何属性,并且因为它没有 nonce 它被 CSP 拒绝.

So essentially why that particular line throws the error is that the appended tag is actually a new tag with the same code and no attributes applied to it and as it has no nonce it's rejected by CSP.

更新:我已经修补了 jQuery 来解决这个问题(是 3.1.2-pre 修补但通过了所有测试),如果你使用我的最后一个修复,我建议更新到这个版本!

Update: I've patched jQuery to fix this issue (is 3.1.2-pre patched but passing all tests), if you used my last fix I recommend updating to this version!

缩小:http://pastebin.com/gcLexN7z

未缩小:http://pastebin.com/AEvzir4H

分支在此处可用:https://github.com/Brian-Aykut/jquery/tree/3541-csp

问题链接:https://github.com/jquery/jquery/issues/3541

代码变化:

第 ~76 行将 DOMEval 函数替换为:

Line ~76 replace DOMEval function with:

function DOMEval( code, doc, attr ) {
    doc = doc || document;
    attr = attr || {};
    var script = doc.createElement( "script" );
    for ( var key in attr ) {
        if ( attr.hasOwnProperty( key ) ) {
            script.setAttribute( key, attr[ key ] );
        }
    }
    script.text = code;
    doc.head.appendChild( script ).parentNode.removeChild( script );
}

attr 添加到 ~line 5717 上的 var 语句到

Add attr to var statement on ~line 5717 to

var fragment, first, scripts, hasScripts, node, doc, attr,

将第 5790 行附近的 else 正文更改为:

Change else body near line 5790 to:

attr = {};
if ( node.hasAttribute && node.hasAttribute( "nonce" ) ) {
    attr.nonce = node.getAttribute( "nonce" );
}
DOMEval( node.textContent.replace( rcleanScript, "" ), doc, attr );

这篇关于jQuery 3.1.1 违反 CSP 指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆