CSPViolationReportBody: blockedURL 属性

CSPViolationReportBody 接口的只读属性 blockedURL 是一个字符串值,表示因违反 内容安全策略 (CSP) 而被阻止的资源。

一个包含值或 URL 的字符串,该值或 URL 代表违反策略的资源。

如果该值不是资源的 URL,则它必须是以下字符串之一:

inline

内联资源。例如,当 CSP 中未指定 'unsafe-inline' 时使用的内联脚本。

eval

eval()。例如,使用了 eval() 但 CSP 中未指定 'unsafe-eval'

wasm-eval

Wasm 评估。例如,使用了 eval() 但 CSP 中未指定 'wasm-unsafe-eval'

trusted-types-policy

违反 trusted-types CSP 指令的资源。例如,使用 window.trustedTypes.createPolicy() 创建了一个 TrustedTypePolicy,但其名称未在 CSP 的 trusted-types 指令中列出。

trusted-types-sink

违反 require-trusted-types-for CSP 指令的资源。例如,该指令设置为 script,但文档未使用 TrustedTypePolicy 来在将数据传递给 Element.innerHTML 等接收器之前进行清理。

示例

以下示例展示了会产生上述 blockedURL 值的 HTML。

示例假设您有一个名为 main.js 的 JavaScript 文件,该文件已从同一域导入到您的脚本中。该脚本(如下所示)会创建一个新的 ReportingObserver 来观察类型为 "csp-violation" 的内容违规报告。每次调用回调函数时,我们都会在 reports 数组的第一个条目中记录 blockedURL

js
const observer = new ReportingObserver(
  (reports, observer) => {
    console.log(`blockedURL: ${reports[0].body.blockedURL}`);
  },
  {
    types: ["csp-violation"],
    buffered: true,
  },
);

observer.observe();

请注意,尽管返回的数组中可能有多份报告,但为简洁起见,我们仅记录第一份报告的 blocked URL。

外部资源的 blockedURL

下面的 HTML 设置了一个策略 Content-Security-Policy: default-src 'self',该策略仅允许加载来自同一站点的资源,然后尝试从外部站点 https://apis.google.com 加载脚本。

html
<!doctype html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'" />
    <script src="main.js"></script>
  </head>
  <body>
    <!-- This should generate a CSP violation -->
    <script src="https://apis.google.com/js/platform.js"></script>
  </body>
</html>

记录 blockedURL 的结果将是

blockedURL: https://apis.google.com/js/platform.js

不安全内联资源的 blockedURL

下面的 HTML 展示了会导致 blockedURLinline 的条件。它设置了一个策略 Content-Security-Policy: default-src 'self',该策略不允许执行内联脚本,由于页面包含内联脚本而导致违规。

html
<!doctype html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'" />
    <script src="main.js"></script>
  </head>
  <body>
    <script>
      const int = 4;
    </script>
  </body>
</html>

记录 blockedURL 的结果将是

blockedURL: inline

受信任类型策略资源的 blockedURL

下面的 HTML 展示了会导致 blockedURLtrusted-types-policy 的条件。首先,它定义了一个允许执行 'unsafe-inline' 脚本的策略,以便我们可以创建一个将触发违规的 TrustedTypePolicy。该策略还使用 trusted-types 指令指定允许创建名为 myPolicyTrustedTypePolicy

html
<!doctype html>
<html lang="en">
  <head>
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self' 'report-sample' 'unsafe-inline'; trusted-types myPolicy" />
    <script src="main.js"></script>
  </head>

  <body></body>

  <script>
    const policy = trustedTypes.createPolicy("somePolicy", {
      // Some (insufficient) sanitization code
      createHTML: (string) => string.replace(/</g, "&lt;"),
    });
  </script>
</html>

在脚本中,会创建一个名为 somePolicy 的策略。

注意:上面定义的特定策略并非一个好的策略。使用受信任类型 (trusted types) 的目的是强制执行某个策略,而不是强制执行特定策略,并确保清理代码集中且易于审查。

由于此策略未在 trusted-types 指令中列出,因此这是一个 CSP 违规,我们会看到日志输出

blockedURL: trusted-types-policy

如果我们更改允许策略的名称为 somePolicy,则页面将不再违反策略。

受信任类型接收器的 blockedURL

下面的 HTML 展示了会导致 blockedURLtrusted-types-sink 的条件。首先,它定义了一个允许执行 'unsafe-inline' 脚本的策略,并且与前一个示例一样,它使用 trusted-types 指令指定允许创建名为 myPolicyTrustedTypePolicy

此外,它还指定了 require-trusted-types-for 'script' 指令,该指令强制要求接收器只能接收使用受信任类型清理过的内容。

html
<!doctype html>
<html lang="en">
  <head>
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self' 'report-sample' 'unsafe-inline'; trusted-types 'myPolicy'; require-trusted-types-for 'script'" />
    <script src="main.js"></script>
  </head>
  <body>
    <input type="text" id="userInput" />
    <button>Update Content</button>
    <div id="content"></div>
  </body>

  <script>
    function updateContent() {
      const userInput = document.getElementById("userInput").value;

      // Passing unsanitized content - a violation of the policy
      document.getElementById("content").innerHTML = userInput;
    }

    document.querySelector("button").addEventListener("click", updateContent);
  </script>
</html>

updateContent() 方法会将未经清理的内容传递给元素的 innerHTML 属性,这将导致 CSP 违规。我们会看到日志输出

blockedURL: trusted-types-sink

为了避免违规,我们需要更新脚本以定义一个受信任类型策略,并使用它来清理传递给元素的输入。

js
const policy = trustedTypes.createPolicy("myPolicy", {
  // Some (insufficient) sanitization code
  createHTML: (string) => string.replace(/</g, "&lt;"),
});

function updateContent() {
  const userInput = document.getElementById("userInput").value;
  const sanitizedInput = policy.createHTML(userInput);
  document.getElementById("content").innerHTML = sanitizedInput;
}

规范

规范
内容安全策略级别 3
# dom-cspviolationreportbody-blockedurl

浏览器兼容性

另见