运行 `npm i -s` 时究竟发生了什么
当你输入 npm i -s你做的不仅仅是安装依赖项;你正在修改项目的供应链。 此 -s flag 是 flag 的缩写 -保存运行 `npm i -s` 或 `npm install --save` 会安装一个包并将其记录在 `/etc/npm/packages/` 目录中。 依赖 你的部分 的package.json从那时起,每个运行的环境 npm安装 将下载相同的依赖项。
计费示例:
# Adds express to dependencies
npm i -s express
这很方便,但也存在持久性问题。如果软件包来源未经验证,或者依赖树中包含不受信任的软件包,实际上就等于锁定了一个潜在的攻击途径,该途径会遍及每次构建、每个环境和每位开发人员的机器。 未经核实的包裹可能包含:
- 隐藏的网络回调
- 数据泄露代码
- 自动运行的安装后脚本
npm i -s 命令本身并不危险,但它安装的内容以及安装位置可能会打开 npm 恶意软件的大门,这些恶意软件会在不知不觉中危害您的项目。
攻击者如何利用 npm 传播恶意软件包
攻击者喜欢 npm,因为它处于现代应用程序开发的核心地位。每次开发者运行 `npm install --save` 命令时,如果依赖项来源没有经过仔细验证,就存在被攻击的机会。
常见攻击媒介
- 注册近似域名: 攻击者发布名称与热门软件包相似的软件包。 示例:安装 特快 而不是 特快 通过 npm i -s 命令,多余的“s”会加载一个木马程序包。
- 依赖混乱: 私有依赖项,例如 @internal/api-client 可能会被同名的公共 npm 包所掩盖。
一旦开发者运行 npm i -s @internal/api-client,就会安装恶意的公共版本。 - 维护者身份受损: 攻击者劫持合法账户或将恶意代码注入受信任的项目,将已知的依赖项变成感染途径。
恶意注入示例:
❌恶意依赖项代码片段示例
postinstall: node exfiltrate-secrets.js
即使是大型组织也受到了通过 npm 传播的恶意软件包的攻击。 standard npm 安装 – 保存 命令。攻击者利用信任链漏洞,而开发人员往往要等到凭证或数据开始泄露才会注意到。
安装脚本和安装后操作的潜在威胁 Hooks – npm i -s
npm 生态系统允许软件包执行生命周期脚本,例如 安装 or 安装后 自动执行。这对于构建二进制文件很有用,但也为滥用打开了方便之门。 当你运行 `npm i -s` 或 `npm install --save` 时,npm 会自动执行这些脚本,而无需确认。 恶意依赖 可以利用这种行为:
- 启动系统命令
- 在本地环境中创建后门
- 窃取 SSH 密钥、令牌或环境变量
例如(非恶意但有风险的行为):
"scripts": {
"postinstall": "node ./scripts/setup.js"
}
If 安装程序.js 如果上游代码被替换或修改,您的系统可能会在安装过程中静默执行攻击者控制的代码。 In CI/CD pipelines,在哪里 npm i -s 由于这些程序会在构建过程中自动运行,因此风险会不断增加。一个恶意 npm 包就可能危及构建代理,窃取环境密钥,或篡改部署工件。
为什么仅靠 npm i -s 手动审查包是不够的
开发人员通常认为检查 的package.json 文件或阅读仓库的README文件并不能保证安全。 一次执行 `npm install --save` 命令可能会引入数十个,有时甚至数百个传递依赖项。每个传递依赖项都可能引入漏洞或恶意代码,而这些漏洞或代码在顶级依赖项中并不可见。
现实世界问题:依赖蔓延
一个只有 20 个直接依赖的项目,很容易产生 500 多个传递依赖。手动审查这些依赖几乎是不可能的。攻击者利用这种复杂性,将恶意 npm 包隐藏在依赖树的深处。
安全使用依赖剂的简易检查清单
- 绝大部分储备使用 npm审计 以及 npm ls 识别隐藏的依赖关系。
- 在运行 npm i -s 之前,请检查软件包作者和最后更新日期。
- 避免从未经验证的网址或 Git 仓库安装。
- 检查可疑脚本(安装, 准备, 安装后)摄影作品通过 的package.json.
- 使用锁定版本 包lock.json 并启用签名验证。
人工审核是一个开始,但要真正起到保护作用,自动化是必不可少的。
将依赖关系扫描和策略控制集成到 CI/CD
现代DevSecOps pipelines 必须将每次执行 `npm i -s` 命令都视为 npm 恶意软件入侵的潜在入口点。依赖项扫描并非可选项,而是构建流程规范的一部分。
自动化策略
- 静态依赖关系扫描: 在构建阶段之前,使用自动扫描器检查已知的恶意或易受攻击的软件包。
- 签名验证: 通过哈希值比较或签名元数据验证软件包完整性。
- 政策执行: 阻止未经核实的来源安装。
例如: pipeline 配置:
security-scan:
script:
- xygeni scan --dependencies --npm --detect-malicious
- xygeni enforce --policy supplychain.yaml
将其整合到您的 CI/CD 确保每次执行 `npm install --save` 命令都会经过验证。任何不符合策略、未签名、未知或存在风险的软件包都会被自动阻止。 这不仅可以保护构建系统,还可以防止下游生产环境受到污染。
构建可信赖的供应链:从 npm 到生产环境
安全防护并不止于安装阶段。每一条 `npm i -s` 命令都会影响你的软件供应链,如果未经验证,就会存在风险。
建立端到端的信任:
- 产生 SBOMs(软件物料清单)跟踪每个软件包的版本和来源。
- 使用已签署的授权书: 采用包裹签名或签名验证方式确保包裹真实性。
- 在每个阶段进行验证: 不仅要在持续集成 (CI) 阶段应用完整性检查,还要在部署和运行时阶段应用完整性检查。
- 隔离构建: 在沙箱中运行安装程序,以防止未经授权的网络或文件访问。
以下是 API 环境中安全 cookie 配置的示例,这种配置通常会通过受感染的依赖项暴露出来:
安全版本,下载,验证,然后执行
# ✅ Secure cookie setup
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict
这些措施,再加上自动化依赖项扫描,可以在 npm 恶意软件包通过您的供应链传播之前将其消除。
结论:在 npm 保护你之前,先保护好你的 npm 安装。
每一条 `npm i -s` 或 `npm install --save` 命令引入的不仅仅是功能,它还引入了信任。而未经验证的信任是存在风险的。
为了保护您的软件供应链:
- 自动依赖关系验证
- 强制执行签名和完整性验证
- 持续扫描 npm 恶意包
- 尽早屏蔽未经核实的信息来源 CI/CD
西吉尼 帮助 DevSecOps 团队检测和阻止恶意 npm 依赖项,强制执行包策略,并监控构建完整性,确保您安装的内容正是您想要运行的内容。
因为在供应链安全中,预防不是一个构建步骤,而是一个基础。





