加载脚本时出现内容安全策略错误
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: ...
,
)
);
【讨论】:
以上是关于加载脚本时出现内容安全策略错误的主要内容,如果未能解决你的问题,请参考以下文章