第三方脚本与 SRI 审计
你的页面加载的每个第三方脚本都以页面的全部权限运行——它能读取 DOM、监听表单输入、在访客的会话中操作。本审计抓取页面的静态 HTML,列出它引用的每个外部脚本,标出哪些是第三方、哪些带子资源完整性(SRI)哈希、哪些锁定了确切版本——并为缺少完整性的第三方脚本计算 sha384 哈希,让你可以直接粘贴进标签。
最后更新:
担心你站上的某个厂商脚本被改动或宕机?用 myeventwatch 免费监控——到期和宕机提醒,无需绑卡。
本审计检查什么——以及它看不到什么
检查器抓取页面一次,解析它被提供的 HTML——仅静态 HTML。其中每个 <script src> 都会连同其主机被列出:主机与页面可注册域名一致时归为第一方,不一致时归为第三方;并检查决定浏览器能否保护你的两个属性:integrity,即浏览器在运行文件前验证的 SRI 哈希;以及 crossorigin,跨源 SRI 检查要生效所必需的属性。URL 中的版本也会被评估:以 [email protected] 或 /v2.4/ 寻址的脚本是已锁定的,而 latest 或无版本的地址是一个移动目标,其内容随时可能在没有人动你的站点的情况下发生变化。
请明确这条边界,因为它很重要:v1 只解析页面的静态 HTML——JavaScript 在运行时注入的脚本不在覆盖范围内。标签管理器、同意工具和聊天组件经常在页面加载后从代码中创建 script 元素,静态解析永远看不到它们。把本审计当作你的模板和 CMS 直接引用的清单——通常是问题中最大、最可修复的部分——标签管理器容器则在管理器自己的预览和变更历史中单独审计。内联脚本(没有 src 的代码块)会作为一项事实计入结果,因为它们根本无法携带 SRI;配套指南会说明如何处理它们。
哈希列:算出来的,绝不猜测
对于缺少 integrity 属性的第三方脚本,检查器会亲自抓取该脚本——通过与本站每个检查器相同的 SSRF 防护抓取路径,上限为前 15 个此类脚本、每个 512 KB——并计算其 SHA-384 哈希。抓取成功时,SRI 列会显示完整的片段 integrity="sha384-…",可直接粘贴到你的标签中,与 crossorigin="anonymous" 并列。只有脚本确实被抓取到时才显示哈希。如果抓取失败、文件过大,或脚本超出了 15 个的上限,该列会改为显示相应的说明——永远不会是占位符或猜测值——修复办法是在你自己的构建流水线中生成哈希,那里有确切的文件在手。
相关检查:安全头检查为响应头评分——包括与 SRI 天然搭档的 Content-Security-Policy;SSL 评分器覆盖这些脚本到达所经过的传输层;配套文章第三方脚本是一种供应链风险剖析了一个真实事件、SRI 能阻止什么和不能阻止什么,以及一套可重复的审计流程。
判定应这样读:带完整性且锁定版本的第三方脚本是健康情形——浏览器会拒绝被替换或编辑过的文件。没有完整性的第三方脚本并非自动就是恶意的;它是未受保护的,意味着它的内容就是其主机今天提供的任何东西,而变更的唯一警告将是损害本身。未锁定的地址应受到与缺失哈希同样的怀疑,因为 latest URL 上的 SRI 哈希会在厂商第一次发布更新时失效——这正是这两个发现并列报告的原因,也是持久修复永远是一对的原因:先锁定确切版本,再对那个确切文件做哈希。
本页展示的事实
| 第三方 | 其主机可注册域名与页面不同的脚本——由别人提供、以你的页面权限运行的代码。 |
| 完整性(SRI) | 标签是否带有 integrity 属性:浏览器在执行文件前核对的加密哈希,任何不匹配都会拒绝执行。 |
| Crossorigin | 标签是否带有跨源 SRI 检查所需的 crossorigin 属性;没有它,浏览器无法对该加载应用 SRI。 |
| 已锁定 | URL 是否指名确切版本(如 [email protected]、/v2.4/),而不是内容可静默变化的浮动 latest 或无版本地址。 |
| 计算出的 SRI | 对于缺少完整性的第三方脚本,检查器通过实际抓取文件计算出的 sha384 哈希——仅在抓取成功时显示,上限前 15 个。 |
常见问题
本审计能看到我的页面运行的每个脚本吗?
不能——本页明说了:v1 只解析页面的静态 HTML,因此 JavaScript 在运行时注入的脚本不在覆盖范围内。标签管理器、A/B 测试工具、同意横幅和聊天组件通常在加载后注入脚本;请在标签管理器中或用浏览器的网络面板审计它们。本审计完整覆盖的是你的已提供 HTML 直接引用的每个脚本——库、CDN 组件和监控嵌入都住在那里。
SRI 列中的哈希从哪里来?
检查器亲自抓取脚本文件并计算其 SHA-384 哈希,对象是缺少 integrity 属性的第三方脚本——前 15 个,每个上限 512 KB。只有脚本确实被抓取到时才显示哈希:如果抓取失败、文件过大或达到上限,该列会改为显示相应说明。把片段连同 crossorigin="anonymous" 一起粘贴到你的 script 标签中,并在任何版本变更后重新运行审计——新版本意味着新哈希。
我的标签管理器脚本无法有固定哈希。怎么办?
没错——标签管理器容器的设计就是要变化的,所以 SRI 无法锁定它;任何用途就是加载变化代码的脚本同理。对这类脚本,控制手段是另一套:限制谁能向容器发布、像审查代码变更一样审查其变更历史、只在需要的页面加载它,并用 Content-Security-Policy 限制注入脚本能做什么、能把数据发到哪里。SRI 保护固定的库;治理保护动态的那些。
缺少 integrity 属性是紧急情况吗?
它是长期暴露,不是事件。该脚本几乎肯定是厂商今天打算提供的文件;问题在于,明天若有不同的文件——在厂商被攻破、账户被劫持或域名过期之后——什么都不会阻止或标记它。修复顺序:先处理带登录、支付或个人数据的页面上的脚本,再在其他所有地方锁定并哈希库,最后处理长尾。版本一旦锁定,每次修复只是一行标签改动。
为什么锁定列把脚本称为“latest”或“无版本”?
锁定判定是对 URL 的启发式读取:像 @1.2.3 或 /v2.4/ 这样像版本的片段算已锁定,显式的 latest 片段算浮动,URL 中任何地方都没有版本算无版本。它被标注为启发式,是因为只有厂商知道自己的发布方案——但安全要点不依赖这个标签:如果那个 URL 上的字节可以在 URL 不变的情况下变化,SRI 哈希就无法存活,所以先锁定,再哈希。