头盔内容安全策略全局路径不起作用

问题描述

我正在使用Helmet使用Express在后端设置Web应用程序的内容安全策略。这些策略如下所示:

const express = require("express");
const app = express();
const helmet = require('helmet');

app.use(helmet());
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],scriptSrc: ["'self'","https://ajax.googleapis.com"],imgSrc: ["https://firebasestorage.googleapis.com"],objectSrc: ["'none'"],styleSrc: ["'self'","https://maxcdn.bootstrapcdn.com/bootstrap","https://www.w3schools.com"],upgradeInsecureRequests: [],},})
);

当我的应用尝试访问诸如https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css之类的链接时。它说它违反了styleSrc策略。但是我已指定允许使用https://maxcdn.bootstrapcdn.com/bootstrap作为策略之一,我认为https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css也将被接受,因为它是一个子src。但是显然它被阻止了。那我如何允许孩子src通过?我已经尝试过https://maxcdn.bootstrapcdn.com/bootstraP*,但是无效。

解决方法

这里是头盔的作者。

尝试添加斜杠,如下所示:

https://maxcdn.bootstrapcdn.com/bootstrap/

这是因为/bootstrap不允许您执行/bootstrap/3.4.0/css/bootstrap.min.css之类的事情,而/bootstrap/却可以。这是内容安全策略,不是头盔。

有关具体细节,请参见the "Matching Source Expressions" section in the CSP spec的步骤11:

如果源表达式包含非空的path-part,并且URL是重定向结果 not ,则:

    如果true的最后一个字符不是U + 002F SOLIDUS字符(path-part)和{{1},请
  1. 精确匹配为/ }}。
  2. source-expression-path-list 是在U + 002F SOLIDUS字符(false)上分割path-part的结果。
  3. 如果 source-expression-path-list 的长度大于 url-path-list 的长度,则返回不匹配。
  4. 对于 source-expression-path-list 中的每个条目
    1. 解码条目的百分比。
    2. 百分比解码 url-path-list 中的第一项。
    3. 如果 entry 不是 url-path-list 中第一项的ASCII区分大小写的匹配项,则返回不匹配
    4. 从列表中弹出 url-path-list 中的第一项。
  5. 如果 exact-match /,并且 url-path-list 不为空,则返回不匹配

顺便说一句,您可能需要将头盔代码清理为类似以下内容:

true

您的代码使用app.use(helmet({ contentSecurityPolicy: { directives: { // ... },},})); (包括一些默认的CSP中间件),然后使用helmet()覆盖它。没什么大不了的,但是只使用一次就更正确了。