浏览器 Web 安全基础系列

  1. 浏览器怎么判断是不是同一个网站

  2. Cookie 为什么会自动携带

  3. Session 登录状态为什么可能被劫持

  4. HTTPS 为什么仍然不够

  5. CORS 到底在限制什么

  6. CSRF 是怎么冒用登录状态的

  7. CSRF 如何防御

  8. XSS 为什么能在你的网站执行

  9. CSP 与浏览器安全响应头

  10. Clickjacking 点击劫持

  11. 第三方资源为什么危险(当前篇)

  12. 防盗链到底防什么

通过 <script src> 加载第三方脚本时,代码虽然来自 CDN,却在当前页面的 Origin 中执行。它可以读取 DOM、localStorage、非 HttpOnly Cookie,并调用本站接口。因此第三方 JavaScript 本质上是把页面权限交给外部供应方。

前端供应链风险

风险来自哪里

  • CDN 文件被篡改;

  • 第三方账号或发布流程被入侵;

  • npm 依赖维护者账号被盗;

  • 依赖被恶意接管;

  • 引用“latest”导致内容无感更新;

  • 统计、客服或广告脚本收集超出预期的数据。

HTTPS 只能保证“你收到的是 CDN 当前提供的内容”,不能保证内容本身仍是你审核过的版本。

SRI 如何工作

Subresource Integrity 让页面声明外部资源的密码学哈希:

<script
  src="https://cdn.example.com/lib-1.2.3.js"
  integrity="sha384-BASE64_HASH"
  crossorigin="anonymous">
</script>

浏览器下载文件后计算哈希。内容与 integrity 不一致时拒绝执行。

SRI 校验流程

生成哈希示例:

openssl dgst -sha384 -binary public/lib.js | openssl base64 -A

然后添加前缀:

sha384-计算结果

SRI 适合什么资源

适合固定版本、内容稳定的外部 JavaScript 和 CSS。若资源每次请求动态变化,哈希会频繁失效。不要引用:

<script src="https://cdn.example.com/lib/latest.js"></script>

应固定版本:

<script src="https://cdn.example.com/lib/1.2.3/lib.min.js"></script>

crossorigin 的作用

跨源资源使用 SRI 时通常需要正确的 CORS 响应和 crossorigin="anonymous"。浏览器需要以允许完整性校验的方式获取资源。CDN 也需要返回适当的 Access-Control-Allow-Origin

CSP 与 SRI 的关系

SRI 验证“这个具体文件内容有没有变化”;CSP 控制“页面允许从哪里加载脚本以及哪些脚本能执行”。组合使用:

Content-Security-Policy: script-src 'self' https://cdn.example.com
<script src="https://cdn.example.com/app.js" integrity="sha384-..." crossorigin="anonymous"></script>

如果 CSP 允许整个大型 CDN,但没有 SRI,CDN 上其他可控路径也可能扩大风险。

自托管是否一定更安全

把依赖下载到自己服务器可以减少运行时第三方变化和可用性依赖,但仍要管理:

  • 依赖来源;

  • 构建机安全;

  • 版本更新;

  • 漏洞扫描;

  • 发布物完整性。

自托管只是把责任转移到自己的供应链,不是自动免疫。

npm 依赖治理

实践中可以:

  • 提交 lockfile;

  • CI 使用 npm ci

  • 审查新增依赖和安装脚本;

  • 定期运行依赖漏洞检查;

  • 减少无必要的小依赖;

  • 使用可信 registry;

  • 固定 CI action 和构建工具版本;

  • 对生产构建产物保留哈希和来源记录。

不要把 npm audit 当作唯一安全判断,它提供的是已知漏洞信息,无法发现所有恶意包和业务误用。

第三方 iframe 的权限隔离

如果第三方功能不需要直接访问主页面 DOM,可以考虑放进跨源 iframe,并使用 sandbox、Permissions-Policy 和严格的 postMessage 协议降低权限:

<iframe
  src="https://widget.example"
  sandbox="allow-scripts allow-forms">
</iframe>

sandbox 权限要按需开放,不能为了“先跑起来”同时放开所有能力。

常见误区

CDN 使用 HTTPS 就足够

HTTPS 防传输篡改,不保证供应方没有被入侵或发布错误内容。

integrity 可以写一次永久不变

依赖升级后内容变化,必须重新计算并审查哈希。

所有第三方代码都能用 SRI

动态脚本、按用户变化的内容不适合固定哈希,应考虑自托管、iframe 隔离或替代方案。

小结

第三方脚本获得的是当前页面脚本权限。应尽量减少数量、固定版本、使用 SRI 和 CSP、审查 npm 依赖,并在可能时通过跨源 iframe 降低权限。供应链安全的目标是让“代码从哪里来、是否被修改、拥有多大权限”都可控。

参考资料