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

Lab*_*ian 3 javascript node.js content-security-policy pug

我正在尝试使用 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 */
Run Code Online (Sandbox Code Playgroud)

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

拒绝加载脚本, '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-...”)。

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

rai*_*7ow 7

正如评论中所表明的,这是破坏这一切的代码行:

app.use(helmet());
Run Code Online (Sandbox Code Playgroud)

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());
Run Code Online (Sandbox Code Playgroud)

是的,很多东西。搞乱你的设置的是这个列表的第一项。以下是该行作为Content-Security-Policy 标头 值发送的默认值:

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
Run Code Online (Sandbox Code Playgroud)

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

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

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

app.use(
  helmet({
    contentSecurityPolicy: {
      useDefaults: false,
      directives: { ... }
    },
  })
);
Run Code Online (Sandbox Code Playgroud)