lirantal/npq
GitHub: lirantal/npq
在 npm 包安装前执行多维启发式安全审计,通过漏洞库查询和十余项包特征检查拦截供应链风险。
Stars: 1633 | Forks: 34
npq 允许你在安装 npm 包_之前_对它们进行审计
[](https://www.npmjs.com/package/npq)
[](LICENSE)
[](https://codecov.io/gh/lirantal/npq)
[](https://github.com/lirantal/npq/actions/workflows/main.yml?query=branch%3Amain)
[](SECURITY.md)
太长不看:如何使用 npq:
```
$ npx npq install express --dry-run
```
_它的作用是:`npx` 工具下载并执行 `npq` 包,对 `express` 包运行安装检查,而 `--dry-run` 表示 npq 无论成功还是出错都会退出_。
这是 npq 实际运行的截图:

关于 npq 的媒体报道:
- 如 [Thomas Gentilhomme](https://github.com/fraxken) 的法文书 [Become a Node.js Developer](https://docs.google.com/document/d/1JHgmEFkc8Py4XSuCB8_DQ5FFEJoogyeninFK6ucTd4o/edit#) 中所述
- Tao Bojlén 的 [A web of trust for npm](https://www.btao.org/2020/10/02/npm-trust.html)
- Zander 的[最喜欢的命令行工具列表](https://zander.wtf/blog/terminal-commands)
- Ran Bar Zik 的[用于安装安全模块的 npq 评测](https://internet-israel.com/%D7%A4%D7%99%D7%AA%D7%95%D7%97-%D7%90%D7%99%D7%A0%D7%98%D7%A8%D7%A0%D7%98/%D7%91%D7%A0%D7%99%D7%99%D7%AA-%D7%90%D7%AA%D7%A8%D7%99-%D7%90%D7%99%D7%A0%D7%98%D7%A8%D7%A0%D7%98-%D7%9C%D7%9E%D7%A4%D7%AA%D7%97%D7%99%D7%9D/%D7%91%D7%93%D7%99%D7%A7%D7%94-%D7%A2%D7%9D-npq-%D7%9B%D7%93%D7%99-%D7%9C%D7%95%D7%95%D7%93%D7%90-%D7%94%D7%AA%D7%A7%D7%A0%D7%94-%D7%AA%D7%A7%D7%99%D7%A0%D7%94-%D7%A9%D7%9C-%D7%9E%D7%95%D7%93%D7%95/)
- ostechnix 的 [How To Safely Install Packages Using Npm Or Yarn On Linux](https://ostechnix.com/how-to-safely-install-packages-using-npm-or-yarn-on-linux)
- debricked 的 [How to evaluate the security of your NPM Package dependencies](https://debricked.com/blog/2020/03/11/how-to-evaluate-the-security-of-your-npm-package-dependencies)
- JavaScript January 实践日历的帖子 [Open Source From Heaven, Modules From Hell](https://www.lirantal.com/blog/2019-01-26)
- Liran Tal 的 [Malicious Modules — what you need to know when installing npm packages](https://www.lirantal.com/blog/malicious-modules-what-you-need-to-know-when-installing-npm-packages-12b2f56d3685)
## 关于
一旦安装了 npq,你就可以安全地*安装包:
```
npq install express
```
`npq` 将通过采用语法启发式并查询 CVE 数据库来执行以下步骤,以健全性检查该包是否安全:
* 查阅 [snyk.io 公开披露的漏洞数据库](https://snyk.io/vuln),以检查该包及其版本是否存在安全漏洞。
* 包在 npm 上的存在时间
* 包的下载次数,作为流行度指标
* 包是否包含 README 文件
* 包是否包含 LICENSE 文件
* 包是否具有安装前/安装后脚本
**重要提示**:npq 在检测到警告(无错误)时默认使用自动继续模式,等待 15 秒后继续安装。你可以通过 `--disable-auto-continue` CLI 标志或 `NPQ_DISABLE_AUTO_CONTINUE=true` 环境变量禁用此行为,以强制执行严格审查和安全加固的安装。有关更多详细信息,请参阅[自动继续文档](docs/feature/auto-continue.md)。
当 npq 完成其信号检查后,它会将实际的包安装工作交给包管理器(默认为 npm,或通过 `NPQ_PKG_MGR` 环境变量指定的包管理器)。
**免责声明**:不存在绝对的保证安全;一个恶意或易受攻击的包仍然可能存在,但未公开披露安全漏洞并通过了 npq 的检查。
## 演示
## 安装
```
npm install -g npq
```
*注意:我们建议使用 `npm` 而不是 `yarn` 进行安装。这样,`npq` 就可以自动为你安装 shell 别名。*
你也可以在 macOS 或 Linux 上通过 [Homebrew](https://brew.sh) 安装 `npq`:
```
brew install npq
```
## 用法
### 使用 npq 安装包
```
npq install express
```
### 融入日常工作
由于 `npq` 是一个前置步骤,用于确保你正在安装的 npm 包是安全的,因此你可以安全地将其嵌入到日常的 `npm` 使用中,这样就不需要记住显式运行 `npq`。
```
alias npm='npq-hero'
```
### 移交给包管理器
如果你使用的是 `yarn`、`pnpm`,或者通常想明确告诉 npq 使用哪个包管理器,你可以指定一个环境变量:`NPQ_PKG_MGR=`
示例:
**使用 yarn 1.x:**
```
alias yarn="NPQ_PKG_MGR=yarn npq-hero"
```
**使用 yarn 4.x:**
```
NPQ_PKG_MGR=yarn yarn run npq-hero
```
或
```
NPQ_PKG_MGR=yarn yarn exec npq-hero
```
**使用 pnpm:**
```
NPQ_PKG_MGR=pnpm npx npq install fastify
```
**使用带别名的 pnpm:**
```
alias pnpm="NPQ_PKG_MGR=pnpm npq-hero"
```
注意:`npq` 默认在对各个包完成尽职调查后,会将所有命令及其参数移交给 `npm`(或指定的其他包管理器)。
## Marshalls(检查员)
| Marshall 名称 | 描述 | 备注
| --- | --- | ---
| age | 如果包在 npm 上的存在时间少于 22 天,将显示警告 | 检查包的创建日期,而不是特定版本
| author | 验证已解析版本的发布者(`_npmUser`),标记该包的**新**维护者(该邮箱在 21 天内首次发布),**休眠维护者**空档期(如果距离他们在该包的最后一次发布超过约 6 个月则发出警告,超过约 9 个月则报错),以及非常**近期**的发布 | 参见 [docs/feature/author-marshall.md](docs/feature/author-marshall.md)
| downloads | 如果包上个月的下载量少于 20 次,将显示警告
| readme | 如果包没有 README,或者被 npm 工作人员检测为安全占位符包,将显示警告
| repo | 如果发现包没有有效且可用的仓库 URL,将显示警告 | 检查最新版本的仓库 URL
| scripts | 如果包具有可能具有恶意的安装前/安装后脚本,将显示警告
| snyk | 如果在 Snyk 数据库中发现包存在漏洞,将显示警告 | 要使 Snyk 正常工作,你需要安装具有有效 API token 的 `snyk` npm 包,或者在 `SNYK_TOKEN` 环境变量中提供该 token,npq 将使用它
| license | 如果发现包没有 license 字段,将显示警告 | 检查最新版本的 license
| expired domains | 如果发现包的某个维护者的电子邮件地址包含过期域名,将显示警告 | 检查依赖版本中拥有过期域名的维护者
| signatures | 将包在注册表 pakument 中显示的签名与发布在 npmjs.com 注册表上的密钥进行比较
| provenance | 将验证已发布包的 provenance 元数据的证明,并在[ provenance 退化](docs/feature/provenance.md)(较旧的 semver 版本拥有注册表 provenance 元数据,但你安装的版本没有)时**报错**
| version-maturity | 如果正在安装的特定版本发布不到 7 天,将显示警告 | 有助于识别可能尚未被社区审查的近期发布版本
| newBin | 如果正在安装的包版本引入了其先前版本中未出现的新的命令行二进制文件(通过 `package.json` 中的 `bin` 字段),将显示警告。 | 有助于识别可能被意外添加到你的 `node_modules/.bin/` 目录中的可执行文件。
| typosquatting | 如果包名与流行包名相似,将显示警告,这可能表明潜在的 typosquatting(误植域名/包名)攻击。 | 有助于识别可能试图通过模仿流行包名来诱骗用户安装它们的包。
| deprecation | 如果包版本在 npm 上被弃用或其 GitHub 仓库已被归档,将显示警告。 | 有助于识别不再维护或推荐使用的包。设置 `GITHUB_TOKEN` 环境变量以获取更高的 GitHub API 速率限制。
### 禁用 Marshalls
要完全禁用某个 marshall,请使用该 marshall 的短名称设置一个环境变量。
例如,要禁用 Snyk 漏洞 marshall:
```
MARSHALL_DISABLE_SNYK=1 npq install express
```
#### 可用的 Marshall 环境变量
以下是用于禁用特定 marshalls 的所有可用环境变量名称:
| Marshall 名称 | 环境变量 | 描述 |
|------------------|-----------------------------------------------|-----------------------------------------------------|
| age | `MARSHALL_DISABLE_AGE` | 禁用包存在时间检查 |
| author | `MARSHALL_DISABLE_AUTHOR` | 禁用包作者验证 |
| downloads | `MARSHALL_DISABLE_DOWNLOADS` | 禁用下载数量检查 |
| expired domains | `MARSHALL_DISABLE_MAINTAINERS_EXPIRED_EMAILS` | 禁用维护者邮箱的过期域名检查 |
| license | `MARSHALL_DISABLE_LICENSE` | 禁用 license 可用性检查 |
| provenance | `MARSHALL_DISABLE_PROVENANCE` | 禁用包 provenance 验证 |
| repo | `MARSHALL_DISABLE_REPO` | 禁用仓库 URL 验证 |
| scripts | `MARSHALL_DISABLE_SCRIPTS` | 禁用安装前/后脚本检查 |
| signatures | `MARSHALL_DISABLE_SIGNATURES` | 禁用注册表签名验证 |
| snyk | `MARSHALL_DISABLE_SNYK` | 禁用 Snyk 漏洞检查 |
| typosquatting | `MARSHALL_DISABLE_TYPOSQUATTING` | 禁用 typosquatting 检测 |
| version-maturity | `MARSHALL_DISABLE_VERSION_MATURITY` | 禁用版本成熟度检查 |
| newBin | `MARSHALL_DISABLE_NEWBIN` | 禁用新引入二进制文件检查 |
| deprecation | `MARSHALL_DISABLE_DEPRECATION` | 禁用弃用状态检查 |
### 在不安装包的情况下运行检查
在没有 `install` / `i` / `add` 子命令的情况下运行 `npq`(例如在包含 `package.json` 的项目目录中)仅审计依赖项,不会运行包管理器。这也适用于 `npq `:仅检查,不传递给安装程序。当你希望 npq 在检查后移交给 npm(或 `NPQ_PKG_MGR`)时,请使用 `npq install …`。
```
npq install express --dry-run
```
### 强制非富文本输出
```
npq install express --plain
```
### 禁用自动继续倒计时
默认情况下,当 npq 仅检测到警告(无错误)时,它会在 15 秒倒计时后自动继续安装。要禁用此行为并始终要求显式确认:
**使用 CLI 标志:**
```
npq install express --disable-auto-continue
```
**使用环境变量:**
```
export NPQ_DISABLE_AUTO_CONTINUE=true
npq install express
```
或者在你的 shell 配置文件(`.bashrc`、`.zshrc` 等)中永久设置它:
```
export NPQ_DISABLE_AUTO_CONTINUE=true
```
当禁用自动继续时,npq 将始终在继续安装之前提示进行显式确认,即使仅检测到警告也是如此。
## 学习 Node.js 安全

## 常见问题解答
1. **`npq` 和 `npq-hero` 有什么区别?**
* `npq` 是一个独立的 CLI,因此它具有 `--dry-run` 等命令行标志(参见 `npq --help`)。但是,当你想将 `npm` CLI 别名化为 NPQ 时,你应该使用 `npq-hero` 作为 npm 别名的可执行文件(例如:`alias npm=npq`),这意味着 `npq-hero` 不能拥有自己的命令行标志,因为它们可能会与 `npm` 可执行文件发生冲突。
2. **我可以在没有 npm 或 yarn 的情况下使用 NPQ 吗?**
* NPQ 会审计包中可能存在的安全问题,但它不能替代 npm 或 yarn。当你选择继续安装该包时,它会将安装过程移交给由你选择的 npm 或 yarn。
3. **NPQ 与 npm audit 有何不同?**
* 即使模块存在漏洞,`npm install` 也会安装该模块;NPQ 会显示检测到的问题,并提示用户确认是否继续安装它。
* NPQ 将在模块的特征上运行合成检查,称为 [marshalls](https://github.com/lirantal/npq#marshalls),例如你将要安装的模块是否具有可能对你的系统有潜在危害的 `pre-install` 脚本,并提示你是否安装它。而 `npm audit` 不会执行任何此类检查,它只查询漏洞数据库以查找已知的安全问题。
* `npm audit` 在功能上更接近 Snyk 所做的工作,而不是 NPQ 所做的。
4. **我需要 Snyk API key 才能使用 NPQ 吗?**
* 这不是必需的。如果 NPQ 无法检测到运行 NPQ 的用户的 Snyk API key,那么它将跳过数据库检查。然而,我们非常鼓励你使用 Snyk,并将其与 NPQ 连接以获得更广泛的安全性。
5. **为什么 NPQ 在安装期间会连接到像 gmail.com 这样的外部域或个人网站?**
* 这不是遥测。NPQ 不收集任何使用数据。在审计包时,NPQ 会获取依赖项的维护者/作者,并检查他们的电子邮件地址,以验证它们是否有效且未与过期域名相关联。过期域名可能会被攻击者滥用,进行账户接管(ATO)攻击,从而使用恶意版本破坏包。因此,NPQ 可能会向 `gmail.com` 或在维护者电子邮件中发现的个人域名发出 DNS 请求。此外,NPQ 还会向 `osv.dev` 发出 HTTP 请求以获取安全漏洞数据(或者如果已配置,则使用 Snyk 作为优先选项)。
## 贡献
请查阅 [CONTRIBUTING](CONTRIBUTING.md) 获取有关为本项目做贡献的指南
## 作者
Liran Tal 跟随 Liran Tal 学习 Node.js 安全编码技术和最佳实践
标签:CMS安全, Cutter, DevSecOps, GNU通用公共许可证, JavaScript, MITM代理, Node.js, npm, npm依赖, SOC Prime, 上游代理, 代码安全, 包管理器, 安全防护, 安装前检查, 开发工具, 暗色界面, 漏洞枚举, 统一API, 自定义脚本