
**你的 AI agent 发布了代码。immunogen 确保它没有携带“感染”。**
[](https://www.npmjs.com/package/immunogen)
[](https://github.com/Mocinjay/immunogen/actions/workflows/ci.yml)
[](./LICENSE)
[](https://nodejs.org)
A · 免疫 · B · 健康 · C · 有症状 · D · 已感染 · F · 危急
在发布之前,为 AI 构建的应用程序提供一份干净的健康证明。immunogen 是一款静态、离线优先的扫描工具,专为使用 Cursor、Claude Code、Lovable、Bolt、v0 或 Replit 构建的代码库而设计——它从不执行你的代码,只读取一次,并返回一个 0–100 的 **Ship Score(交付评分)**,涵盖 11 个类别,包括 AI 层本身(skills、MCP servers、agent/system 提示词)——这是大多数扫描器完全忽略的领域。
## 快速开始
```
npx immunogen
```
在你的项目目录中运行它——它会完全离线扫描当前文件夹,不需要 API key,并打印包含交付评分的终端报告。使用 `npx immunogen ./path/to/app` 指向其他路径。
## 示例输出
针对一个故意被“污染”的测试应用运行:
```
GRADE: F — Critical
Ship Score: 0/100 — High risk
Verdict: blocked
Critical: 17 High: 34
CRITICAL SEC-05 .env:1
Committed environment file (.env) found in the scanned tree. [confidence: HIGH]
CRITICAL SEC-01 .env:2
Hardcoded Stripe live secret key (sk_live_) found in source. [confidence: HIGH]
matched: sk_l****
CRITICAL SEC-04 .env:3
Reference to SUPABASE_SERVICE_ROLE_KEY found in source. [confidence: HIGH]
matched: SUPA****
CRITICAL PAY-01 app/api/stripe/webhook/route.ts:3
Stripe webhook handler does not verify the signature (missing constructEvent). [confidence: HIGH]
CRITICAL AUTH-01 app/api/stripe/webhook/route.ts:8
Exported Next.js route handler POST has no authentication or authorization check. [confidence: MEDIUM]
matched: POST
CRITICAL AUTH-01 app/api/users/route.ts:5
Exported Next.js route handler GET has no authentication or authorization check. [confidence: MEDIUM]
matched: GET
CRITICAL AUTH-01 app/debug/route.ts:5
Exported Next.js route handler GET has no authentication or authorization check. [confidence: MEDIUM]
matched: GET
```
🔴 **已污染——发布前请隔离。** 上方的每一项命中都是检测到的污染物,带有 `ruleId` 和精确的 `file:line`——机密信息已被脱敏,绝不完整打印。
## 健康等级说明
`GRADE:` 行是在 0–100 的交付评分之上叠加的一个 A–F 级头条评级——评分、评级区间和最终判定
仍会在其下方完整报告,
不作任何更改。
| 等级 | 状态 | 含义 |
|---|---|---|
| **A** | 免疫 | 评分 90–100 — 健康状况良好,可随时发布 |
| **B** | 健康 | 评分 75–89 — 有轻微问题,风险较低 |
| **C** | 有症状 | 评分 55–74 — 中等风险,值得在发布前修复 |
| **D** | 已感染 | 评分 35–54 — 高风险,发布前必须解决 |
| **F** | 危急 | 评分 0–34,**或出现任何单个 CRITICAL(危急)级别发现** — 无论数字评分为多少,均自动判定不合格 |
任何 CRITICAL 发现都会自动判定为 `F` — 单个泄露的生产环境机密
或未经身份验证的支付路由会使等级降至最低,
即使所有其他类别都一尘不染,这与已应用于数字交付评分的 CRITICAL 硬上限如出一辙。
## 为什么选择 immunogen
immunogen 不是唯一针对 AI 构建应用的扫描器——但它是唯一一款**确定性、免费且离线,覆盖代码库*以及*在线 URL *以及* AI 层**,并且能输出 SARIF 以供 CI 门禁使用的工具。清单式的工具依赖于你的 AI 助手进行检查(因此结果不可复现),而托管的扫描器是一项付费服务,只能探测已部署的 URL。
| | **immunogen** | [vibe-check.cloud][vc] | [benavlabs/vibe-check][bv] | [Vibe App Scanner][vas] |
|---|:---:|:---:|:---:|:---:|
| 免费 / 开源 | ✅ MIT | ✅ | ✅ MIT | ❌ 付费 |
| 确定性引擎 — 无 LLM,可复现 | ✅ | ❌ AI 驱动 | ❌ AI 驱动 | ~ 托管 |
| 静态代码库扫描(从不执行你的代码) | ✅ | ✅ | ✅ | ❌ 动态 |
| 在线 URL / 部署应用扫描 | ✅ | ❌ | ❌ | ✅ |
| 扫描 **AI 层** (skills / MCP / agent 提示词) | ✅ 深度 | ~ 部分 | ❌ | ❌ |
| 用于 CI 门禁的 SARIF 输出 | ✅ | ❌ | ❌ | ❌ |
✅ 是 · ~ 部分 · ❌ 否 / 未记录。截至 2026 年 7 月,与各工具的公开文档和 README 进行了对比 — 发现有误?欢迎提交 PR。
## 扫描内容
代码库扫描包含 11 个类别和 17 个检测器——此外,当你扫描在线 URL 时,还会增加第 12 个类别的 5 个 Web 探测检测器——专门针对编码 agent 悄无声息地发布的那些会阻碍上线的问题。
| 类别 | 捕获内容 |
|---|---|
| Secrets (机密信息) | 硬编码的提供商密钥 (Stripe, AWS, OpenAI),提交的 `.env` 文件,高熵 token |
| Client-bundle 泄露 | 带有秘密名称的环境变量通过 `NEXT_PUBLIC_`/`VITE_` 前缀泄露到浏览器中 |
| Auth & RLS (身份验证与行级安全) | 未经身份验证的路由处理器,开放的 Firebase 规则,缺失的 Supabase 行级安全 |
| 支付安全 | 跳过签名验证的 Stripe webhook 处理器 |
| Dependencies (依赖项 OSV) | 通过 OSV.dev batch API 发现的直接依赖项中已知的 CVE,支持离线回退 |
| Injection / XSS (注入 / XSS) | 未经清理的 `dangerouslySetInnerHTML` |
| CORS & headers (CORS 与标头) | 带有凭证的通配符 CORS,缺失的 Content-Security-Policy |
| Storage (存储) | 公开的 Firebase/Firestore/Storage 规则,不受管控的 Supabase 存储桶 |
| Legal (法律合规) | 当应用收集用户数据时,缺失的隐私政策/服务条款界面 |
| Config / debug (配置 / 调试) | 将完整的 `process.env` 转储到日志或调试 endpoint |
| ⭐ AI 层 | skills、rules 和 agent 提示词中的提示词注入字符串、数据渗透模式以及 MCP 工具投毒/最小权限漏洞 — 这是大多数扫描器会跳过的一层 |
## 架构
```
repo → ingest (walk + AST cache) → detectors (17, 11 categories) → Ship Score → reporters (terminal · json · sarif)
```
## CLI 用法
```
immunogen
[--format terminal|json|sarif] [--no-llm] [--authorize] [--allow-private]
```
- `` — 要扫描的代码库路径,或要检测的在线 `https://`/`http://` URL。
- `--format terminal|json|sarif` — 输出格式(默认为 `terminal`)。`json` 是稳定的、机器可读的 `ScanResult`;`sarif` 适用于 GitHub code scanning / 其他支持 SARIF 的工具。
- `--no-llm` — 禁用 LLM 修复提示词增强。这已经是默认行为;该 flag 的存在是为了在脚本/CI 中保持明确性。
- `--authorize` — 检测在线 URL 目标所需的同意授权门禁(参见[扫描在线 URL](#screen-a-live-url))。当 `` 为本地代码库时无效。
- `--allow-private` — 逃生舱口,允许在线 URL 检测以 loopback/private/link-local 主机为目标(仅限本地开发/测试)。
- **退出码:** 判定为 `blocked`(已污染)时为 `1`,判定为 `pass`(已通过)时为 `0`,扫描完全无法运行时(路径错误、缺少 `--authorize`、拒绝私有主机等)为 `2` — 可直接将其放入 CI 门禁中使用。
### 库用法
```
import { scan } from "immunogen";
const result = await scan("./my-app");
console.log(result.score, result.findings);
```
`scan(path, options?)` 返回一个 `ScanResult`:`{ target, scannedAt, stackHints, findings, score, llmEnriched, scanIncomplete }`。`score` 是一个 `ShipScore` (`{ score, grade, gradeLabel, band, verdict, criticalCount, highCount }`);`findings` 是一个按严重程度排序的 `Finding[]`,包含 `file`/`line`/`ruleId`/`category`/`confidence`。
### 可选的 LLM 修复提示词
默认情况下,immunogen 绝不调用 LLM。要为 HIGH/CRITICAL 发现启用由 Claude 或 OpenAI 生成的可复制粘贴修复提示词,请设置:
| 环境变量 | 用途 |
|---|---|
| `IMMUNOGEN_PROVIDER` | `anthropic` 或 `openai` — 选择适配器 |
| `ANTHROPIC_API_KEY` | 当 `IMMUNOGEN_PROVIDER=anthropic` 时必填 |
| `OPENAI_API_KEY` | 当 `IMMUNOGEN_PROVIDER=openai` 时必填 |
| `OPENAI_BASE_URL` | 可选的 OpenAI 兼容 endpoint 覆盖(例如本地 Ollama 服务器) |
如果既没有配置环境变量的提供商,也没有匹配的 key,immunogen 将静默保持离线状态(无网络调用,无错误)。每个发现的代码片段在发送给任何提供商之前都会被脱敏——任何完整的源代码或匹配到的机密文本都绝不会未经脱敏离开你的机器。
## 扫描在线 URL
```
immunogen https://myapp.com --authorize
```
immunogen 还可以直接扫描已部署的网站,而不仅仅是本地代码库。这是针对目标自身基础设施的一次真实且受限的探测——因此 `--authorize` 是一个必须的授权门禁,而不是一个装饰性的 flag:**只扫描你拥有的或被明确授权测试的网站。**
它在活动目标上检查的内容:
- **Security headers(安全标头)** — 缺失/薄弱的 `Content-Security-Policy`、HSTS、`X-Frame-Options`、`X-Content-Type-Options`、`Referrer-Policy` (`WEB-HDR`)。
- **CORS 配置错误** — `Access-Control-Allow-Origin: *` 结合了 `Access-Control-Allow-Credentials: true`,以及反射源变体 (`WEB-CORS`)。
- **暴露的文件** — 公开提供的 `.env`、`.git/config`/`.git/HEAD`、`config.json`,或泄露的 `.js.map` source map (`WEB-EXPOSED`)。
- **提供 bundle 中的机密** — 在同源 script bundle 或内联 `