0

我正在使用 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*了,但是无效。

4

1 回答 1

1

头盔的作者在这里。

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

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

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

有关详细信息,请参阅CSP 规范中“匹配源表达式”部分的第 11 步:

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

  1. 如果 的最后一个字符不是U+002F SOLIDUS 字符 ( ),则设精确匹配,否则。truepath-part/false
  2. source-expression-path-listpath-part为U+002F SOLIDUS 字符 ( /)上拆分的结果。
  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. 如果完全匹配true,并且url-path-list不为空,则返回不匹配

顺便说一句,您可能希望将您的 Helmet 代码清理为如下所示:

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      // ...
    },
  },
}));

您的代码使用helmet(),其中包括一些默认的 CSP 中间件,然后用helmet.contentSecurityPolicy(). 没什么大不了的,但只使用一次更正确。

于 2020-09-25T21:25:15.237 回答