加载脚本时出现内容安全策略错误

Posted

技术标签:

【中文标题】加载脚本时出现内容安全策略错误【英文标题】:Content Security Policy error while loading a script 【发布时间】:2021-09-15 16:22:30 【问题描述】:

我正在尝试使用 Pug 在我的应用中呈现图表,如下所示:

block content
  h2 Question statistics
    .col-lg-12 
      script(src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js")
      .chart-container
        canvas#myChart2      
          script.
            var ctx = document.getElementById("myChart2").getContext('2d');
            ctx.canvas.parentNode.style.width = '50%'
            var idata = [1]    
            var ilabel = [2] 
            var myChart = new Chart(ctx,  /* ... etc */

这在一周左右之前加载得很好,但是今天当我尝试访问此功能时,图表不会呈现。 我的控制台中的错误是这样的:

拒绝加载脚本 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js' 因为它违反了以下内容安全政策指令: "script-src 'self'"。请注意,'script-src-elem' 没有明确 设置,所以 'script-src' 用作后备。

拒绝执行内联脚本,因为它违反了以下内容 内容安全策略指令:“script-src 'self'”。无论是 'unsafe-inline' 关键字,一个哈希 ('sha256-AklvVxShqs4WBi3vUz7qSiPkes2rSVGoNyoZXYVnSA8='),或随机数 ('nonce-...') 是启用内联执行所必需的。

这是我第一次看到这个错误,我不知道如何解决它。有什么想法吗?

【问题讨论】:

使用哪个后端服务?知道哪个组件或模块负责在响应中设置 HTTP 标头特别有趣。你能打开页面的源代码并检查它的标题部分吗? @raina77ow 这是由节点 js 提供的 是的,使用 javascript 和 HTTP。我理解了。这里重要的是细节。究竟是什么创建了 HTTP 标头?为什么最近变了? 特别是代码中是否有response.setHeader("Content-Security-Policy", ...之类的东西? “真实”服务器是否位于 nginx 或任何其他代理之后? 不,它只是 res.send('chart.pug') 【参考方案1】:

正如 cmets 所证明的,这行代码打破了这一切:

app.use(helmet());

Helmet 是一个非常简洁的模块,旨在让您保护您的服务器免受最常见的攻击媒介的侵害,而无需过多担心细节。唉,作为任何好的安全工具,它默认以“偏执模式”运行。这条小线实际上相当于:

app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());

是的,很多东西。弄乱您的设置的是此列表的第一项。这是该行以Content-Security-Policy header values 发送的默认值:

default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: data:;
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests

再一次,这是有道理的,因为 Helmet 对您正在使用的外部实体一无所知 - 以及您对这些实体的信任程度。您负责提供此数据,方法是添加哈希信息或在配置中列出受信任的来源。例如:

helmet.contentSecurityPolicy(
  useDefaults: false,
  directives: 
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "example.com"], // scripts from example.com are now trusted
    objectSrc: ["'none'"],
    upgradeInsecureRequests: [],
  ,
)

您可以单独配置每个模块,也可以直接将此配置添加到头盔中:

app.use(
  helmet(
    contentSecurityPolicy: 
      useDefaults: false,
      directives:  ... 
    ,
  )
);

【讨论】:

以上是关于加载脚本时出现内容安全策略错误的主要内容,如果未能解决你的问题,请参考以下文章

facebook 聊天进入网站时出现内容安全策略错误?

内容安全策略间歇性错误

内容安全策略 [错误] 拒绝加载脚本 safari

Vimeo 内容安全策略错误 - 拒绝加载脚本

拒绝加载脚本,因为它违反了以下内容安全策略指令

Chrome 扩展“拒绝加载脚本,因为它违反了以下内容安全策略指令”