前端构建和依赖供应链安全要关注哪些风险?
简化版
前端供应链安全要关注恶意依赖、依赖混淆、安装脚本、泄露 npm token、构建环境注入、锁文件篡改和 CDN 资源被污染。防护重点是锁定依赖、审计依赖、最小化 token 权限、保护 CI 密钥、限制 install scripts、产物可追溯。
详细版
常见风险:
- 安装恶意 npm 包。
- typo-squatting 包名拼写攻击。
- 依赖维护者账号被盗。
- postinstall 脚本执行恶意命令。
- CI 中泄露 npm token、Sentry token、API key。
- 构建产物被替换或 CDN 污染。
- lockfile 被恶意改写。
常见防护:
- 提交 lockfile 并使用 frozen install。
- 定期依赖审计和升级。
- CI secret 最小权限和分环境管理。
- 发布 token 使用自动化可信发布。
- 对高风险脚本和新增依赖做 review。
- 构建产物带版本和校验。
完整版教学
一、前端依赖树天然很大
一个现代前端项目直接依赖可能只有 50 个,但传递依赖可能有 1000 个以上。每个依赖都是供应链的一环。只要其中一个包被投毒,就可能在安装、构建或运行时影响项目。
这也是为什么供应链安全在前端尤其重要。前端项目安装依赖频繁、构建自动化程度高、发布到 CDN 面向所有用户,一旦出问题影响面很大。
业务项目
├─ direct deps 50
└─ transitive deps 1000+
└─ 任一高权限脚本都可能成为风险点
二、安装脚本是高风险入口
npm 包可以定义 preinstall/postinstall 等脚本,安装时自动执行。正常用途包括编译原生模块、下载二进制文件;恶意用途则可能读取环境变量、上传 token、篡改文件。
如果 CI 环境里有 npm 发布 token、私有仓库 token、错误监控 token,恶意 postinstall 就可能读取并外传。防护上要尽量减少安装阶段暴露的密钥,并对新增依赖保持 review。
| 风险点 | 例子 | 防护 |
|---|---|---|
| postinstall | 读取环境变量 | 最小化 CI secret |
| 拼写攻击 | lodashs | 依赖 review |
| lockfile 改写 | 替换 tarball | frozen install |
| token 泄露 | npm publish token | 最小权限和轮换 |
三、lockfile 是安全边界之一
lockfile 记录依赖版本和解析信息。它能防止 semver 范围在不同时间解析出不同版本,也能让代码 review 看到依赖树变化。如果 lockfile 被恶意改写,就可能把包指向异常版本或源。
CI 应使用 npm ci、pnpm install --frozen-lockfile 等命令,确保 lockfile 和 package 声明一致。不要让 CI 自动修 lockfile 后继续构建。
pnpm install --frozen-lockfile
pnpm audit
pnpm build
四、依赖审计不能只看数量
自动 audit 会报很多漏洞,但不代表每个都同等紧急。要看漏洞是否在生产依赖、是否可达、是否运行在浏览器、是否影响构建阶段。盲目升级也可能引入 breaking change。
数字例子:100 个 devDependency 漏洞可能都在本地测试工具里,生产风险较低;1 个运行时 XSS 相关依赖漏洞可能影响所有用户。安全处理要按影响面和可利用性排序。
五、CI 密钥要最小权限
构建环境常有各种 secret:npm token、部署 token、Sentry token、私有 registry 凭据。它们应按环境、任务和权限拆分。构建 PR 不应该拥有生产发布权限,发布 token 不应该能管理整个账号。
如果开源项目接受外部 PR,更要注意不要在不可信 PR 上暴露 secrets。很多供应链事故不是代码漏洞,而是 CI 权限边界太宽。
六、产物要可追溯和可验证
发布产物应该能追溯到 git commit、构建流水线和依赖锁。出现线上问题时,要知道这份 JS 来自哪次构建。高安全要求项目还会做产物签名、SRI、SBOM 或 provenance。
安全钩子:前端供应链的核心问题不是“我写的代码安不安全”,而是“我执行和发布了谁的代码”。
七、常见误区与追问
- 误区:前端代码跑在浏览器,供应链风险不高。 构建阶段和发布产物都可能被污染,影响所有用户。
- 误区:audit 没红就绝对安全。 audit 只能发现已知漏洞,恶意包和权限泄露仍需流程防护。
- 误区:devDependency 没风险。 dev 依赖能在 CI 构建阶段执行脚本,也可能窃取密钥。
- 追问:如何降低 postinstall 风险? 减少安装阶段 secret、审查新增依赖、必要时限制 scripts。
- 追问:为什么 frozen lockfile 重要? 防止 CI 自动解析出未审查的依赖树。
- 追问:npm token 如何管理? 使用最小权限、自动化发布、定期轮换,避免本地长期明文保存。
八、加强记忆
供应链安全用“锁依赖、审脚本、管密钥、追产物”来记。lockfile 和 frozen install 保证依赖树可审查,install scripts 和新增依赖要谨慎,CI secrets 最小权限,发布产物能追溯到 commit 和流水线。前端安全不只在浏览器里,也在安装和构建链路里。