JQuery的3.1.1违反CSP指令

问题描述 投票:8回答:2

我使用jQuery 3.1.1版,我想实现我的网页内容安全策略指令。

我收到以下错误:

拒绝了,因为它违反了以下内容安全策略指令执行内嵌脚本:“脚本的src‘自我’‘现时-c20t41c7-73c6-4bf9-fde8-24a7b35t5f71’”。无论是“不安全内联”的关键字,散列(“SHA256-KAcpKskREkEQf5B3mhDTonpPg34XnzaUC5IoBrOUrwY =”),或者随机数(“随机数-...”)是必需的,以使内联执行。

该错误是在主的jquery.js脚本文件82系产生的。这条线的内容是:

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

基本上,它增加了一个内嵌脚本标签的DOM,违反了CSP。

我不想用'unsafe-inline'。是否有任何其他方式来规避这个错误?

正如你可以在CSP违反看,我用CSP级别2(随机数),但会被忽略。有没有可能(一些如何)通知jQuery来使用这个随机数追加脚本标记是什么时候?


UPDATE:这是HTML的样子(使用随机数快速模板)

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

一旦HTML呈现,在脚本标签的现时属性由服务器发送的CSP现时指令相匹配。


更新:它与普通的JavaScript工作

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

如果没有现时属性这个脚本标签将违反CSP指令。

jquery content-security-policy
2个回答
2
投票

看起来它如何追加内嵌脚本结束丢弃所有的属性,我看不出修复它来测试它我用下面的HTML的一种明显的方式的jQuery的错误或怪癖:

<!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追加它经过以下过程(降低少许):

  • 创建一个文档片段并添加脚本标签给它
  • 应用一个type="false/"属性的脚本标签
  • 删除type属性
  • 如果src属性存在,它检索通过AJAX脚本(没有作进一步调查)
  • 如果没有它运行DOMEval( node.textContent.replace( rcleanScript, "" ), doc )

DomEval看起来像这样(添加了评论):

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

正如你可以看到它被附加和CSP等失败之前没有属性会结转到新的元素。

该解决方案是只使用本地JS的元素追加,而不是jQuery的或可能等待一个bug修复/响应您的报告。我不能确定什么他们的推理是排除以这种方式为内嵌脚本标记可能是安全功能的属性?

下面应该达到你想要什么,而不jQuery的 - 刚刚成立的属性的textContent你的JS代码。

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

所以基本上,为什么那个特定的行抛出的错误是,在所附的标签实际上是用相同的代码创建一个新标签,并没有适用于它的属性和它没有nonce它是由CSP拒绝。

更新:我已经jQuery的补丁来解决这个问题(是3.1.2预修补,但通过所有测试),如果你用我的最后一次定方位,我建议升级到这个版本!

精缩: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功能:

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 );
}

添加attrvar声明〜行5717到

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

更改else傍身行5790到:

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

1
投票

哈OK,你只是想包括jQuery的,所以你需要重新定义函数的appendChild(禁用它)jQuery的脚本之前和删除您的自定义功能后。

<script>
    var oldAppend = document.head.appendChild
    document.head.appendChild = function(script){
        if(script && script.tagName=='SCRIPT'){
            document.createElement('fakeHead').appendChild(script)//because script need a parent in the line that create the error
            return script
        }
        return oldAppend.apply(this,arguments)
    }
</script>
<script nonce="<%=nonce%>" type="text/javascript" src="jquery.js"></script>
<script>
    document.head.appendChild = oldAppend
</script>

编辑:试试这个,这将重新定义的jQuery的附加功能

var oldAppend = $.fn.append
$.fn.append = function($el){
    var dom = ($el instanceOf $) ? $el[0] : $el
    if(dom && dom.tagName=='SCRIPT'){
        this[0].appendChild(dom)
        return this
    }
    return oldAppend.apply(this,arguments)
}
© www.soinside.com 2019 - 2024. All rights reserved.