【问题标题】:Refused to apply inline style because it violates the following Content Security Policy directive拒绝应用内联样式,因为它违反了以下内容安全策略指令
【发布时间】:2013-07-19 23:06:15
【问题描述】:

所以,大约 1 小时后,我的扩展程序就失败了。

我正在做我的扩展,它正在做我假装的事情。我做了一些更改,因为我不喜欢我删除了它们,现在我的扩展程序抛出错误:

拒绝应用内联样式,因为它违反了以下内容 内容安全策略指令:“default-src 'self'”。注意 'style-src' 没有明确设置,所以 'default-src' 被用作 后备。

是什么导致了这个错误?

我在以下方面进行了更改:

popup.html

<!DOCTYPE html>
<html ng-app="PinIt" ng-csp>
    <head>
        <link rel="stylesheet" href="css/popup.css">
        <script src="js/lib/jquery-1.8.2.min.js"></script>
        <script src="js/lib/angular.min.js"></script>
        <script src="js/app/app.js"></script>
        <script src="js/app/popup.js"></script> 
    </head>
    <body id="popup">
        <header>
            <h1>PinIt</h1>
        </header>
    <div ng-controller="PageController">
            <div>{{message}}</div>
            <h2>Page:</h2>
            <div id="elem">{{title}}</div>
            <div>{{url}}</div>
            <h2>Imagens:</h2>
            <ul>
                <li ng-repeat="pageInfo in pageInfos" style="list-style: none">
                    <div class="imgplusshare">
                    <img src={{pageInfo}} class="imagemPopup"/>
                    <ul class="imas">
                      <li id="liFacebook" ng-click="fbshare(pageInfo)">
                      <span>
                      <img src="facebook_16.png"/>Facebook
                      </span>
                    </li>
                    <li id="liTwitter" ng-click="twshare(pageInfo)">
                    <span>
                    <img src="twitter-bird-16x16.png"/>Twitter
                    </span>
                    </li>
                    <li id="liGooglePlus" ng-click="gpshare(pageInfo)">
                    <span><img src="gplus-16.png"/>Google+</span>
                    </li>
                    <li id="liEmail" ng-click="mailshare(pageInfo)">
                    <span><img src="mail_icon_16.png"/>Email</span>
                    </li>
                    <hr>
                    </ul>

                    </div>
                    </li>

                    </ul>
</div>
    </body>
</html>

popup.js

  myApp.service('pageInfoService', function() {
        this.getInfo = function(callback) {
            var model = {};

            chrome.tabs.query({'active': true},
            function (tabs) {
                if (tabs.length > 0)
                {
                    model.title = tabs[0].title;
                    model.url = tabs[0].url;

                    chrome.tabs.sendMessage(tabs[0].id, { 'action': 'PageInfo' }, function (response) {

                        model.pageInfos = response;

                        callback(model);
                    });

                }

            });
        };
    });
    myApp.controller("PageController", function ($scope, pageInfoService) {

        pageInfoService.getInfo(function (info) {           
            $scope.title = info.title;
            $scope.url = info.url;
            $scope.pageInfos = info.pageInfos;
            $scope.fbshare =  function($src) {
             chrome.windows.create({url:"http://www.facebook.com/sharer/sharer.php?u="+$src});
      };    
            $scope.twshare =  function($src) {
             chrome.windows.create({url:"https://twitter.com/intent/tweet?url="+$src});
      };
            $scope.gpshare =  function($src) {
             chrome.windows.create({url:"https://plus.google.com/share?url="+$src});
      };
            $scope.mailshare =  function($src) {
             chrome.windows.create({url:"mailto:?subject=Imagem Partilhada por PinIt&body=<img src=\""+$src+"\"\\\>"});
      };



            $scope.$apply();


        });
    });

这是我的清单文件:

{
    "name": "PinIt",
    "version": "1.0",
    "manifest_version": 2,

    "description": "Pin It",
    "icons": {
        "128": "icon128.png"
    },
    "browser_action": {
        "default_icon": "img/defaultIcon19x19.png",
        "default_popup": "popup.html",
        "default_title": "PinIt"
    },
    "content_scripts": [ {
    "js": [ "js/lib/jquery-1.8.2.min.js", "js/app/content.js", "js/jquery-ui-1.10.3.custom.js" ],
    "matches": [ "*://*/*" ],
    "run_at": "document_start"
    } ],
    "minimum_chrome_version": "18",
    "permissions": [ "http://*/*", "https://*/*", "unlimitedStorage", "contextMenus", "cookies", "tabs", "notifications" ],
    "content_security_policy": "default-src 'self'"
}

有什么建议吗?

【问题讨论】:

标签: javascript google-chrome-extension content-security-policy


【解决方案1】:

正如错误消息所说,您有 CSP 禁止的内联样式。我在您的 HTML 中至少看到一个 (list-style: none)。而是将该样式放入您的 CSS 文件中。

为了进一步解释,内容安全政策不允许内联 CSS,因为它可能很危险。来自An Introduction to Content Security Policy

"如果攻击者可以注入一个 直接包含一些恶意负载的脚本标签.. 浏览器没有机制来区分它和合法的 内联脚本标签。 CSP 通过禁止内联脚本解决了这个问题 完全:这是唯一的方法 当然。”

【讨论】:

  • 这对我来说没有任何意义。对于内联scripts,我理解,但这个问题是关于内联styles。是否可以注入恶意的内联样式?
  • 这是搜索的第一个结果[恶意内联样式]:dontkry.com/posts/code/disable-inline-styles.html
  • 该页面上的参数似乎无效。它使用非内联样式的示例来演示您可能想要阻止内联样式的原因。它给出的例子确实是你可以用 CSS 做的坏事,但你为什么只阻止内联样式,而不是例如,所有的 CSS?
  • @Trejkaz dontkry 页面上提到的样式内联样式。在这种情况下,“内联”包括&lt;style&gt; 元素,而不仅仅是style= 属性; -inline 意味着将link rel="Stylesheet" 元素放在head 中。关键是它是针对XSS 的安全防护,我们假设XSS 攻击者可以将任何内容添加到页面的body,但不能将link rel="Stylesheet" 添加到head
  • 因为有人可以使用 css 将任何文本添加到您的网站。想想:":after{content:"You are hacked", fontSize:666}
【解决方案2】:

您还可以通过添加 style-src 'self' 'unsafe-inline'; 来放松 CSP 的样式

"content_security_policy": "default-src 'self' style-src 'self' 'unsafe-inline';" 

这将允许您在扩展程序中继续使用内联样式。

重要提示

正如其他人所指出的,这是推荐的,您应该将所有 CSS 放在一个专用文件中。请参阅OWASP explanation,了解为什么 CSS 可以成为攻击的载体(链接至 @KayakinKoder)。

【讨论】:

【解决方案3】:

另一种方法是使用 CSSOM(CSS 对象模型),通过 DOM 节点上的 style 属性。

var myElem = document.querySelector('.my-selector');
myElem.style.color = 'blue';

更多关于 CSSOM 的细节: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.style

正如其他人所说,为 css 启用 unsafe-line 是解决此问题的另一种方法。

【讨论】:

    【解决方案4】:

    根据http://content-security-policy.com/ 最佳起点:

        default-src 'none'; 
        script-src 'self'; 
        connect-src 'self'; 
        img-src 'self'; 
        style-src 'self';
        font-src 'self';
    

    切勿内联样式或脚本,因为它会破坏 CSP 的目的。您可以使用样式表设置样式属性,然后使用.js 文件中的函数来更改样式属性(如果需要)。

    【讨论】:

      【解决方案5】:

      您可以在 Content-security-policy 中使用 add "img-src 'self' data:;" 并使用大纲 CSS。不要使用内联 CSS。它对攻击者是安全的。

      【讨论】:

      • 以上答案之一已经解决了这个问题。
      【解决方案6】:

      好吧,我认为为时已晚,到目前为止,许多其他人都有解决方案。

      但我希望这可以帮助:

      我将 react 用于身份服务器,因此“不安全内联”根本不是一个选项。如果您查看控制台并实际阅读 CSP 文档,您可能会发现解决问题的方法有以下三种:

      1. 如果您的项目使用 CSP,则“unsafe-inline”是不安全的,这是出于一个原因,它就像丢弃完整的策略一样,与根本没有 CSP 策略是一样的

        1. 'sha-XXXCODE' 这很好,安全但不是最佳的,因为有很多手动工作,每次编译 SHA 可能会改变,所以很容易成为噩梦,只有在脚本或样式是不太可能改变,参考文献很少

        2. 随机数。这是赢家!

      Nonce 的工作方式与脚本类似

      CSP 标头 ///csp 东西 nonce-12331

      <script nonce="12331">
         //script content
      </script>
      
      

      由于csp中的nonce与标签相同,所以会执行脚本

      对于内联样式,nonce 也以属性的形式出现,因此适用相同的规则。

      所以生成随机数并将其放在你的内联脚本中

      如果你使用 webpack,也许你使用的是 style-loader

      下面的代码可以解决问题

      
      module.exports = {
        module: {
          rules: [
            {
              test: /\.css$/i,
              use: [
                {
                  loader: 'style-loader',
                  options: {
                    attributes: {
                      nonce: '12345678',
                    },
                  },
                },
                'css-loader',
              ],
            },
          ],
        },
      };
      
      

      【讨论】:

      • 不,您不应该对 nonce 进行硬编码。这些应该为每次加载动态生成,否则它们就像根本没有 CSP 一样不安全。
      • 关于如何为静态 SPA 的每次负载生成随机数的建议?
      猜你喜欢
      • 2015-09-26
      • 2017-11-13
      • 2021-05-14
      • 2020-12-21
      • 2020-06-23
      • 1970-01-01
      • 2020-08-24
      • 2012-11-27
      • 2015-09-21
      相关资源
      最近更新 更多