Jenkins错误 - 在<URL>中阻止脚本执行,因为文档的框架被沙盒化且未设置'allow-scripts'权限。

53

我知道如果在HTML中使用iFrame,我们必须对它进行沙箱化,并将'allow-scripts'权限设置为true。

但我的问题是,我的纯Angular JS应用程序中根本没有iFrame。当我在本地运行它时,它可以正常工作。

但一旦我将其部署到服务器上,Chrome就会显示此错误消息以及以下错误:

拒绝加载样式“bootstrap.min.css”,因为它违反了以下内容安全策略指令:“style-src 'self'”。

在'dashboard.html'中 阻止脚本执行 因为文档的框架已被沙箱化,而'allow-scripts' 权限未设置。

我没有从第三方站点或其他地方调用该页面,这可能会注入我的源代码并使其出现在iFrame中。我检查了代码,并确认根本没有iFrame。

顺便说一下,我使用非常旧的Chrome(26)和Firefox(10)[组织限制]。IE11也是如此(虽然没有显示错误消息),页面不会加载。

这是什么原因?我错过了什么吗?任何指针都将不胜感激。

下面是我尝试做的事情的快照...已经删除了微不足道的部分...

<html lang="en" ng-app="dashboard">
   <head>
      <title>Dashboard</title>
      <link href="css/bootstrap.min.css" rel="stylesheet">
      <script src="js/jquery.min.js"></script>
      <script src="js/angular.min.js"></script>
      <script src="js/ui-bootstrap-tpls-0.6.0.js"></script>
      <script src="js/bootstrap.min.js"></script>
      <script src="js/notifications.js"></script>
      <style>
         body { background-color: #F3F3F4; color: #676a6c; font-size: 13px;}
      </style>
      <script>
         var dashboardApp = angular.module('dashboard', ['ui.bootstrap', 'notificationHelper']);
         
         Type = {
            APP : 0, CTL : 1
         }
         
         
         function DashboardCtrl($scope, $location, $timeout, $http, $log, $q) {
            $scope.environments = [ { ... }];
            $scope.columns = [ { ... } ];
         
             $scope.Type = window.Type;
            $scope.applications = [{ ... }];
         
            $scope.selectedEnv = null;
         
            var resetModel = function(applications) {
                applications.forEach(function(app) {
                     var hosts=$scope.findHosts(app, $scope.selectedEnv);
                     if(hosts){
                         hosts.forEach(function(host){
                             $scope.initStatus(app.status,host);
                         });
                     }
                });
            };
         
            var timeoutPromise = null;
         
             $scope.initStatus = function (status,host) {
                 status[host]=[{
                     ...
                 }];
         
             };             
         }
         
      </script>
   </head>
   <body ng-controller="DashboardCtrl">
      <div class="request-notifications" ng-notifications></div>
      <div>
         <tabset>
            <tab ng-repeat="env in environments" heading="{{env.name}}" select="set(env)" active="env.tab_active">
               <div class="col-md-6" ng-repeat="column in columns" ng-class="{'vertical-seperator':$first}">
                  <div class="panel" ng-class="{'first-child':$first}">
                     <div class="panel-heading">
                        <h3>{{column.column}}</h3>
                     </div>
                     <div class="panel-body">
                        <div class="frontends" ng-repeat="layer in column.layers">
                           <h4>{{layer.name}}</h4>
                           <div class="category" ng-repeat="category in layer.categories" ng-class="category.css">
                              <div class="category-heading">
                                 <h4>{{category.name}}</h4>
                              </div>
                              <div class="category-body group" ng-repeat="group in category.groups">
                                 <div ng-if="!env[group.host]">
                                    <h4>{{group.name}}</h4>
                                    <span class="label label-danger">Not deployed</span>
                                 </div>
                                 <div ng-repeat="host in env[group.host]">
                                    <div class="group-info">
                                       <div class="group-name">{{group.name}}</div>
                                       <div class="group-node"><strong>Node : </strong>{{host}}</div>
                                    </div>
                                    <table class="table table-striped">
                                       <thead>
                                          <tr>
                                             ...
                                          </tr>
                                       </thead>
                                       <tbody>
                                          <tr class="testStatusPage" ng-repeat="app in apps | filter: { column: column.column, layer: layer.name, category: category.name, group: group.name } : true">
                                             <!-- Application Home Links -->
                                             <td class="user-link" ng-if="app.type === Type.A || app.type === Type.A1 || app.type === Type.B || app.type === Type.B1 || app.type === Type.C"><a href="{{app.link}}">{{app.text}}</a></td>                                                                                          <td ng-if="app.status[host].statusCode == 0" class="result statusResult"><span class="label label-success">Success</span></td>
                                             <td ng-if="app.status[svr].status != null && app.status[host].status != 0" class="result statusResult"><span class="label label-danger">{{app.status[host].error}}</span></td>
                                          </tr>
                                       </tbody>
                                    </table>
                                 </div>
                              </div>
                           </div>
                        </div>
                     </div>
                  </div>
               </div>
            </tab>
         </tabset>
      </div>
   </body>
</html>
6个回答

56

我们将这段HTML内容放在Jenkins的userContent目录中。最近我们升级到了最新的Jenkins 1.625 LTS版本,发现他们引入了新的内容安全策略,会向响应头添加以下标头,导致浏览器拒绝执行样式表和JavaScript等任何东西。

X-Content-Security-Policy: sandbox; default-src 'none'; img-src 'self'; style-src 'self';

为了解决这个问题,我们需要通过在Jenkins中重置以下属性来删除这个标题。
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

升级到 Jenkins 1.625 并使用 userContent 文件夹的人可能会受到此更改的影响。

有关更多信息,请参见https://wiki.jenkins-ci.org/display/JENKINS/Configuring+Content+Security+Policy


1
嗨@Venkat,在从Firefox设置此值后,现在在Jenkins中可以工作了,但是在Chrome浏览器中仍然显示此错误:“因为它违反了以下内容安全策略指令:“script-src 'unsafe-inline'”。有人知道如何再次防止出现此错误吗? - Alter Hu
@AlterHu - 你确定 script-src: unsafe-inline 是来自 Jenkins 的吗?根据文档,这些头部将不会被添加。默认规则设置为:sandbox; default-src 'none'; img-src 'self'; style-src 'self'; - Venkat
2
这不是官方Jenkins网站的内容,而是来自某个人的回答,类似于Nakilon在下面的评论。我发现问题的根本原因是Chrome浏览器需要重新启动并完全清除会话,然后你就可以在Jenkins中看到HTML页面了。你的回答很棒。 - Alter Hu
谢谢确认 :) 很高兴我的回答有所帮助。 - Venkat

45

实现以下解决方案需要按照以下步骤操作:

  1. 打开Jenkins首页。
  2. 进入“管理Jenkins”页面。
  3. 现在进入“脚本控制台”页面。
  4. 在控制台中粘贴下面的语句,然后点击运行。 System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")
  5. 之后它将加载CSS和JS。

注意:如果按照上述步骤仍然无法加载CSS和JS,则清除浏览器缓存和Cookie并刷新页面。


2
(清除CSP属性后,)我需要重新运行测试,然后CSS和脚本将被加载。 - Yuci
这是否完全覆盖(放宽)了安全实现?恢复到先前状态的命令应该是什么? - ronnyfm
@ronnyfm-重新启动你的Jenkins,它将恢复到先前的状态。 - Ronak Jain
嗨,@RonakJain的解决方案对我有用,谢谢。此外,重新启动Jenkins可以恢复先前的状态。 有没有一个永久的解决方案?即使重新启动,Jenkins也不会恢复先前的状态。 - undefined

29

我也曾遇到HTML Publisher Plugin的同样问题。

Jenkins的新内容安全策略(Content Security Policy),你可以通过设置以下内容来绕过它:

hudson.model.DirectoryBrowserSupport.CSP=script-src 'unsafe-inline';

UPDATE: 由于某些原因,对于Jenkins 2.x版本,我必须再次更新参数,使用空CSP值而不是 script-src 'unsafe-inline来完全显示外部HTML页面:

-Dhudson.model.DirectoryBrowserSupport.CSP=

在Windows中,在Jenkins主目录中有一个jenkins.xml文件,您可以在其中设置全局JVM选项,如Jenkins系统属性。只需将其添加到参数标记下:

<arguments> -Xrs -Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle "-Dhudson.model.DirectoryBrowserSupport.CSP= " -jar "%BASE%\jenkins.war" --httpPort=8080 </arguments>

对于大多数Linux发行版,您可以修改文件中的JENKINS_ARGS:

/etc/default/jenkins (或jenkins-oc)

对于CentOS,需要修改文件中的JENKINS_JAVA_OPTIONS

/etc/sysconfig/jenkins (或jenkins-oc)

在内容安全策略参考文献中可以找到更多示例: http://content-security-policy.com/


2
全局MAVEN_OPTS用于传递参数给Maven,而不是Jenkins。因此,它自然不起作用。相反,您应该从Jenkins脚本控制台中的“管理Jenkins”链接中设置此属性:System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "") - Venkat
3
在Jenkins脚本控制台中运行System.setProperty()仅对当前Jenkins会话有效,因此您需要在下次Jenkins重新启动后再次运行它!但是,在Jenkins服务Java参数中设置它将使其全局生效。 - Noam Manos
1
是的,你说得对,确实应该这样做。 - Venkat
嗨@Venkat,在Firefox中设置了这个值后,现在在Jenkins中可以工作了,但是对于Chrome浏览器,它仍然显示以下错误:因为它违反了以下内容安全策略指令:“script-src 'unsafe-inline'”。有人知道如何再次防止出现此错误吗? - Alter Hu
@Nakilon - 你为什么编辑只是为了在参数中添加<strike>标签? 这破坏了jenkins.xml。 请解释或撤消。 - Noam Manos
显示剩余2条评论

9

针对运行在Ubuntu上的Jenkins:

  1. put to /etc/default/jenkins

    JAVA_ARGS="${JAVA_ARGS} -Dhudson.model.DirectoryBrowserSupport.CSP=\"\" "
    
  2. visit http://<your jenkins hostname>/safeRestart

(关于此选项和其他选项: https://wiki.jenkins.io/display/JENKINS/Features+controlled+by+system+properties)

更新:这一次我执行 /safeRestart 时不够,我不得不执行 sudo service jenkins restart


3

以上回答在我使用Ubuntu 16.04和Jenkins 2.46.2时没有起作用。我不得不在/etc/default/jenkins中更改JAVA_ARGS参数:

JAVA_ARGS="-Djava.awt.headless=true  -Dmail.smtp.starttls.enable=true -Dhudson.model.DirectoryBrowserSupport.CSP=\"sandbox allow-scripts; style-src 'unsafe-inline' *;script-src 'unsafe-inline' *;\""

更多信息在这里


我还添加了“沙盒允许同源”选项。 - Gwen

0
在 Amazon Linux 上,在 /etc/sysconfig/jenkins 的底部更改:

#JENKINS_ARGS="-Dhudson.model.DirectoryBrowserSupport.CSP=sandbox"

JENKINS_ARGS="-Dhudson.model.DirectoryBrowserSupport.CSP=\"\""

在 Amazon Linux 2 中,这个方法不起作用,但我已经在同一个文件中更改了不同的配置:从: JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true"到: JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dhudson.model.DirectoryBrowserSupport.CSP="default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' 'unsafe-inline' data:;""重新启动 Jenkins 然后看似有效。 - Lukas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接