谷歌浏览器扩展程序内容安全政策

问题描述:

我正在研究谷歌浏览器扩展程序,其中应包括Facebook的sdk.js,但问题是我无法使应用程序工作,因为内容安全策略..这是我的一部分代码:谷歌浏览器扩展程序内容安全政策

的manifest.json

{ 
    "manifest_version": 2, 

    "name": "<app-name>", 
    "description": "<description>", 
    "version": "0.1", 

    "permissions": [ 
    "tabs","<all_urls>" 
    ], 
    "content_scripts": [ 
    { 
    "matches": [ 
    "http://*/*", 
    "https://*/*" 
    ], 
    "js": ["intercept_connections.js"] 
    } 
    ], 
    "content_security_policy": "script-src 'self' https://connect.facebook.net/en_US/ 'unsafe-eval'; object-src 'self'", 
    "background": { 
    "scripts" : ["background.js"] 
    }, 
    "browser_action": { 
     "default_icon": "icon.png", 
     "default_popup": "popup.html" 
    } 
    } 

popup.html

<html> 
<head> 
    <title>Facebook Mass Sharer</title> 


    <script type="text/javascript" src="popup.js"></script> 
    <script type="text/javascript" src="FbApi.js"></script> 
</head> 

<body> 
<body> 
    <h1>Post to Facebook</h1> 
    <button id="postTest">TestMe</button> 

    </body> 
</body> 
</html> 

popup.js

var handleClick = function() { 
    postToGroup(<groupID>); 
} 

var initialize = function() { 
    var test = document.getElementById('postTest'); 
    test.addEventListener("click",handleClick); 
} 

window.addEventListener("load", initialize); 

FbApi.js(我做的)

window.onload = function() { 
    window.fbAsyncInit = function() { 
     FB.init({ 
      appId  : '<appID>', 
      xfbml  : true, 
      version : 'v2.1', 
      oauth  : true 
     }); 
     }; 

     (function(d, s, id){ 
     var js, fjs = d.getElementsByTagName(s)[0]; 
     if (d.getElementById(id)) {return;} 
     js = d.createElement(s); js.id = id; 
     js.src = "https://connect.facebook.net/en_US/sdk.js"; 
     fjs.parentNode.insertBefore(js, fjs); 
     }(document, 'script', 'facebook-jssdk')); 
} 

var postToGroup = function(groupID) { 
    FB.api(
    "/"+groupID+"/feed", 
    "POST", 
    { 
     "message": "This is a test message" 
    }, 
    function (response) { 
     if (response && !response.error) { 
     /* handle the result */ 
     } 
    } 
); 
} 

事情是我不断收到此错误:

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

我试图改变"content_security_policy": "script-src 'self' https://connect.facebook.net/en_US/ 'unsafe-eval'; object-src 'self'""content_security_policy": "script-src 'self'; object-src 'self'"或 “content_security_policy”:"script-src 'self' https://connect.facebook.net/en_US/ 'inline-eval'; object-src 'self'"为在错误中建议,但没有运气。我应该尝试什么?

+0

你能看到什么是抛出该错误?这听起来像Facebook可能在某处使用eval。 – jmort253 2014-08-31 20:34:21

+0

在Facebook的API使用eval的一次有......看看[https://connect.facebook.net/en_US/sdk.js](here)..Just搜索EVAL,你会发现它一个time..But我正在使用'unsafe-eval',所以我不知道我的错误在哪里 – csanonymus 2014-08-31 20:42:53

+0

我很确定Google认为eval不安全。我不认为你可以重写它。您需要做的是使用该内容的iframe,以便无法访问任何Chrome API。然后,您需要使用postMessage在iframe和扩展的主要部分之间进行通信。 – jmort253 2014-08-31 20:44:39

谷歌认为eval是一个不安全,潜在危险的操作,因为动态内容可能会进入应用程序/扩展并自行运行,从而可以访问整个强大的chrome世界。访问文件系统和其他通常禁止使用普通网站JavaScript的资源。

因此,在您的扩展和应用程序使用这些CSP-违反库的唯一办法就是sandbox them

我们通过列出扩展包内的特定HTML文件为被沙盒做到这一点。每当加载沙盒页面时,它将被移动到唯一的来源,并且将被拒绝访问chrome。* API。如果我们通过iframe将这个沙箱页面加载到我们的扩展中,我们可以传递它的消息,让它以某种方式处理这些消息,并等待它传递给我们一个结果。这种简单的消息传递机制为我们提供了在扩展的工作流程中安全地包含eval驱动代码所需的一切。

总之,你需要在你的扩展中创建一个额外的组件,一个HTML文件,你的沙盒,以及加载有问题的Facebook代码。然后,您将在沙盒页面中添加监听器,该监听器可以从包含的HTML页面接收消息,然后处理扩展中的事件。这可以保护您的用户免受eval攻击,因为eval'd代码无法访问沙箱中的任何Chrome API。

当我使用sipml5的JavaScript SIP库时,我遇到了同样的问题。该库非常宽松地使用eval,因此使用该库的唯一方法是在沙箱中。我创建了一个小型库,用于处理在沙箱和主应用程序之间同步存储数据,称为Sandbox StorageAPI for Chrome™。在代码中,你可以看到我是如何的沙箱和主网页之间的通信:

manifest.json的:

"sandbox": { 
    "pages": ["sandbox.html" ] 
    }, 

炫魅。HTML:

<!-- Sandboxed page --> 
    <iframe height="800" width="1200" id="sandboxFrame" class="sandbox active" src="sandbox.html" style=""></iframe> 

storageAPI.js:

在这里,我在监听应用/扩展与沙箱“注册”本身的主体,部分安全沙箱创建一个监听器然后存储参考,因此沙箱可以传送回主模块:

window.addEventListener('message', function(event) { 
      console.info("Message received from wrapper = " + JSON.stringify(event.data)); 
      console.info("location = " + window.location.href); 
      switch(event.data.command) { 

       case 'initStorageAPI': 
        storageAPI.storage = event.data.storage; result = "It's alive!!!"; 
        storageAPI.sandbox.window.onload(); 
        console.info("Prepare to postMessage back to the wrapper..."); 
        storageAPI.wrapper = event; 
        event.source.postMessage({'command':'initStorageComplete','result': result}, event.origin); 

这里的地方,我们将数据发送回主模块的例子:

storageAPI.setItem = function(key, value) { 
     if(storageAPI.CHROME_EXTENSION == false) { 
      return window.localStorage.setItem(key, value); 
     } else { 
      storageAPI.storage[key] = value; 
      // send back to the wrapper to store 
      storageAPI.wrapper.source.postMessage({'command':'writeStorage', 'storage': storageAPI.storage}, storageAPI.wrapper.origin); 

     } 

    }; 

总之,您可以使用一种类似的技术来将数据来回/从沙箱来回/从主模块来回,将不安全的库连接到扩展的安全,敏感的部分。有关更多详细信息,请参阅文档。

记住的iframe甚至可以隐藏。你真的只需要它就可以运行不安全的代码。

免责声明:我是沙盒StorageAPI为Chrome™开发人员。我不隶属于Google或Chrome,所有商标都属于Google。

+0

CSP strict-dynamic的任何想法都无法用于Chrome扩展程序? – Pacerier 2017-08-12 14:13:14