elaz48/langdoctor
GitHub: elaz48/langdoctor
一款专为 LangGraph/LangChain 项目设计的离线安全与生产就绪扫描器,用于在发布前发现已知 CVE 及框架特有的安全隐患。
Stars: 0 | Forks: 0
# langdoctor 🩺
[](https://pypi.org/project/langdoctor/)
[](https://pypi.org/project/langdoctor/)
[](https://github.com/elaz48/langdoctor/actions/workflows/ci.yml)
[](LICENSE)

## 快速开始
```
pipx run langdoctor # or: uvx langdoctor
```
```
langdoctor # scan the current directory
langdoctor path/to/project # scan a specific directory
langdoctor list-checks # every check, with IDs and severities
langdoctor --version # tool version + advisory DB date
```
## 为什么需要它
2026 年对 agent 技术栈来说是艰难的一年:
- **Langflow 正遭受主动攻击。** `CVE-2025-3248`(未授权 RCE)已被
加入 [CISA KEV 目录](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
并[被用于部署 Flodrix 僵尸网络](https://www.trendmicro.com/en_us/research/25/f/langflow-vulnerability-flodric-botnet.html);
`CVE-2026-5027`(路径遍历 → RCE)[正在约 7,000 个暴露的实例中被利用](https://www.bleepingcomputer.com/news/security/path-traversal-flaw-in-ai-dev-platform-langflow-exploited-in-attacks/)。
- **LangGraph checkpointer CVE** — SQLite/base checkpointer 中的 SQL 注入和不安全的反序列化可通过伪造的 checkpoint 链式触发 RCE。
- **供应链攻击** — 针对该生态系统依赖的 CI action 和包(tj-actions 和 LiteLLM 事件)意味着固定到 tag 的 action 或未锁版本的依赖项是一个真实的风险面。
这些正是框架专用的 linter 能在你发布前捕获的问题。langdoctor 随包携带 CVE 数据并完全离线运行。
## 检查内容
| ID | 类别 | 严重程度 | 捕获内容 |
| --- | --- | --- | --- |
| `LD101` | 已知 CVE | 高 | SQLite checkpointer 中通过 metadata 过滤键进行的 SQL 注入 |
| `LD102` | 已知 CVE | 中 | 加载 checkpoint 时不安全的 msgpack 反序列化 |
| `LD103` | 已知 CVE | 中 | 加载 checkpoint 时不安全的 JSON 反序列化 |
| `LD104` | 已知 CVE | 高 | 旧版 load_prompt 函数中的路径遍历 |
| `LD105` | 已知 CVE | 严重 | dumps/loads 中利用序列化注入提取密钥 |
| `LD106` | 已知 CVE | 严重 🔴KEV | /api/v1/validate/code 中的未授权 RCE (Langflow) |
| `LD107` | 已知 CVE | 中 | BaseCache 对不可信数据的反序列化可能导致 RCE |
| `LD108` | 已知 CVE | 高 | JsonPlusSerializer 的 "json" 模式中的 RCE |
| `LD109` | 已知 CVE | 高 | SQLite store 实现中的 SQL 注入 |
| `LD110` | 已知 CVE | 高 | SqliteStore 中通过过滤键进行的 SQL 注入 |
| `LD111` | 已知 CVE | 高 🔴KEV | 通过 /api/v2/files 上传的路径遍历 → RCE (Langflow) |
| `LD150` | 已知 CVE | 高 | 低于当前安全基线 (1.10.1) 的 Langflow |
| `LD201` | Checkpointer 与状态 | 高 | 面向生产环境的项目中使用了 MemorySaver |
| `LD202` | Checkpointer 与状态 | 中 | SqliteSaver 可能在写入并发下崩溃 |
| `LD203` | Checkpointer 与状态 | 高 (启发式) | Checkpoint 历史记录受用户控制输入过滤 |
| `LD204` | Checkpointer 与状态 | 中 | 带有 interrupts 的已编译图没有 checkpointer |
| `LD301` | 图与运行时配置 | 中 | LangGraph 运行未配置 recursion_limit |
| `LD302` | 图与运行时配置 | 低 (启发式) | 创建 LLM 客户端时未设置 timeout |
| `LD303` | 图与运行时配置 | 信息 | 已废弃的 1.0 之前的 LangChain 导入 |
| `LD304` | 图与运行时配置 | 高 | 旧版 load_prompt() 的使用 |
| `LD401` | 密钥与暴露 | 严重 | 源代码中硬编码的 API key |
| `LD402` | 密钥与暴露 | 高 | 存在 .env 文件但未添加至 gitignore |
| `LD403` | 密钥与暴露 | 严重 | 未显式禁用 Langflow 自动登录 |
| `LD501` | 规范 | 中 | 依赖项未锁定版本 |
| `LD502` | 规范 | 中 | GitHub Actions 使用了未锁定版本的第三方 action |
CVE 检查的严重程度源自 CVSS 评分;`🔴KEV` 标记
[已知被利用](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
的漏洞,这些漏洞始终会优先展示。
## CI 集成
### GitHub Action
```
# .github/workflows/langdoctor.yml
name: langdoctor
on: [push, pull_request]
permissions:
contents: read
security-events: write # to upload SARIF
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: elaz48/langdoctor@v1
with:
fail-on: high
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: langdoctor.sarif
```
检测结果将显示在代码库的 **Security → Code scanning** 标签页中。
### pre-commit
```
# .pre-commit-config.yaml
repos:
- repo: https://github.com/elaz48/langdoctor
rev: v0.1.0
hooks:
- id: langdoctor
```
### GitLab CI
```
langdoctor:
image: python:3.12-slim
script:
- pip install langdoctor
- langdoctor --format sarif > gl-langdoctor.sarif
artifacts:
reports:
sast: gl-langdoctor.sarif
```
## 配置
在 `pyproject.toml` 中配置默认值;命令行参数具有更高优先级。
```
[tool.langdoctor]
fail-on = "high" # critical | high | medium | low | never
ignore = ["LD203", "LD302"]
exclude = ["examples", "vendor"]
```
通过 LD ID、CVE 或任何别名在内联代码中抑制单个检测项:
```
API_KEY = get_key() # langdoctor: ignore=LD401
```
```
langgraph==1.0.5 # langdoctor: ignore=LD102
```
被抑制的检测项始终会作为 `suppressed: N` 计数进行报告,因此不会有任何内容被静默忽略。
## 输出格式
`--format console`(默认) · `json` · `sarif` · `markdown`
- **sarif** — GitHub code scanning;`security-severity` 带有真实的 CVSS 值。
- **markdown** — 可直接粘贴到 PR 或 issue 中。
- **json** — 机器可读,包含按严重程度划分的摘要。
退出码:`0` 表示干净(或低于 `--fail-on` 阈值),`1` 表示存在达到/高于阈值的检测项,`2` 表示扫描错误。除非使用 `--strict`,启发式检查绝不会影响退出码。
## langdoctor 不能做什么
- ❌ **不是运行时防护。** 它扫描代码和依赖项;不会介入您的请求路径。
- ❌ **不是 LLM 防火墙。** 它不进行提示注入或内容分析。
- ❌ **不能替代 Semgrep/Snyk。** 它是那些工具遗漏的*特定于框架的*检测层 — 专门针对 LangGraph/LangChain/Langflow 的潜在隐患,按 ID 提供并附带修复方案。
它是确定性的(无 AI 调用)、离线的(CVE 数据随包携带),并且零配置。
## 开发
```
pip install -e ".[dev]"
pytest
ruff check .
```
需要 Python 3.10+。请参阅 [`CLAUDE.md`](CLAUDE.md) 了解设计原则、检查 ID 约定以及“将安全公告视为数据”的模型。
## 许可证
MIT © 2026 elaz48
主题:langgraph · langchain · langflow · security · sast · ai-agents · llm-security · devsecops · cli
标签:图数据库, 逆向工具