一个基于 LangGraph、Trivy、LLM 和 Semgrep 的智能依赖风险分类管道。它将嘈杂的依赖 CVE 发现转化为与仓库相关的可疑点、结构化触点假设和紧凑证据,供人类或编码代理进行下游审查。
这不是一个原始的 Trivy 包装器,也不是最终的漏洞可利用性预言机。
它被设计用于减少噪音并逐步优化依赖漏洞发现:
- 使用 Trivy 检测存在漏洞的依赖
- 验证依赖是否确实在目标仓库中使用
- 从参考资料和公告中丰富 CVE 上下文
- 将每个 CVE 转换为 1-4 个触发面候选
- 生成并运行 Semgrep 规则进行候选级别触点筛选
- 生成紧凑的 Markdown 报告以及结构化中间产物
当前管道为:
trivy_scan -> verify_deps -> cve_enrich -> anchor_triage -> semgrep_scan -> audit_report -> cleanup_tmp
节点职责:
trivy_scan:运行 Trivy,保留高价值 CVE 元数据并记录数据库状态verify_deps:修剪未在代码中实际使用的依赖发现,具有别名感知回退搜索cve_enrich:读取参考资料并将 CVE 文本转换为结构化安全上下文anchor_triage:提出用于静态探测的触发面候选semgrep_scan:生成 Semgrep 规则,验证它们,扫描代码并保留代表性证据audit_report:直接从丰富的 CVE 和候选扫描结果渲染结构化 Markdown 报告cleanup_tmp:占位符清理步骤,目前保留非破坏性用于调试
扫描器最好被理解为依赖风险分类工具:
- 它输出与仓库相关的可疑点,而不是最终的漏洞判决
- 它帮助人类或下游代理专注于值得审查的少数代码路径
- 它适合作为独立 CLI 或内部工作流程步骤,将最终 Markdown 报告移交给下游审计员或编码代理
最终的 audit_report.md 是一个上游分类交接产物。
- 它不是完整的应用程序安全审查
- 可能会出现扫描错误
- 它旨在将依赖版本发现转换为更高 ROI 的代码审查线索
- 下游审查员应确认哪些 CVE 具有真正的代码级别支持,快速降级仅依赖噪音,并避免将任务扩展到不相关的安全发现
- Python 3.11+
- Trivy 已安装并在
PATH中可用 - Semgrep 已安装并在
PATH中可用 - 至少一个配置的 LLM 提供商的 API 访问
Python 依赖:
pip install -r requirements.txt开发依赖:
pip install -r requirements-dev.txt将 .env.example 复制到 .env 并填写您的密钥:
cp .env.example .env主要设置:
LLM_PROVIDER:默认deepseek,可选anthropicDEEPSEEK_API_KEY:DeepSeek 兼容请求的 API 密钥LLM_MODEL:默认提供商的模型名称,默认deepseek-v4-flashLLM_BASE_URL:OpenAI 兼容的基础 URLANTHROPIC_API_KEY:可选的 Anthropic API 密钥ANTHROPIC_MODEL:可选的 Anthropic 模型名称TRIVY_DB_MAX_AGE_HOURS:刷新前数据库最大使用时长TRIVY_DB_UPDATE_POLICY:默认数据库策略,auto|refresh|skip|fail之一TRIVY_UPDATE_RETRIES:初始数据库更新尝试后的重试次数TRIVY_UPDATE_TIMEOUT:Trivy 数据库更新尝试的超时时间
针对目标仓库运行扫描器:
python main.py /absolute/path/to/target/project --language python常用选项:
--language:目标仓库的主要语言--severities:严重性过滤器,默认CRITICAL HIGH--db-update-policy:auto|refresh|skip|fail--db-update-retries:初始更新尝试后的重试次数--db-update-timeout:每次尝试的超时时间(秒)--early-exit:在特定节点后停止用于调试--export-audit-report:接收AUDIT_REPORT.md的可选目录
默认运行时/模型行为:
- 默认提供商是
deepseek - 默认模型是
deepseek-v4-flash - 每次运行在工作流程开始前清除
runtime/tmp和runtime/logs - 正常运行前无需手动运行
clean_tmp.py
运行时行为:
- 每次运行开始时清除
runtime/tmp和runtime/logs - 清理行为与
clean_tmp.py匹配,但现在在启动时自动执行 - 报告导出是可选的;除非提供
--export-audit-report,否则不会复制任何内容 - 如果启用导出,最终报告将复制到
<target>/AUDIT_REPORT.md
数据库策略行为:
auto:仅在本地数据库过时或缺失时更新;如果刷新失败,回退到本地数据库refresh:始终在扫描前刷新;如果刷新不成功则失败skip:从不刷新;需要现有的本地数据库fail:从不刷新;如果本地数据库过时或缺失则失败
示例:
python main.py /absolute/path/to/target/project --language python
python main.py /absolute/path/to/target/project --early-exit verify_deps
python main.py /absolute/path/to/target/project --early-exit semgrep_scan
python main.py /absolute/path/to/target/project --db-update-policy refresh --db-update-retries 2 --db-update-timeout 30
python main.py /absolute/path/to/target/project --export-audit-report /absolute/path/to/output
python main.py /absolute/path/to/target/project --language python --severities MEDIUM HIGH CRITICAL --export-audit-report /absolute/path/to/target/project工具集中在 pyproject.toml 中:
pytestruffmypy
常用检查:
python -m unittest discover -s tests
python -m pytest
python -m ruff check .
python -m mypy运行时输出写入 runtime/ 下:
runtime/tmp/trivy/scan_results.json:原始 Trivy 结果runtime/tmp/trivy/trimmed_cwe_groups.json:使用验证后保留的依赖发现runtime/tmp/trivy/alias_resolution_records.json:第 1 阶段后保留的包到别名映射记录runtime/tmp/trivy/code_evidence_records.json:第 2 阶段后保留的代码搜索证据记录runtime/tmp/trivy/import_alias_cache.json:来自手动映射、注册表查找和 LLM 别名推理的缓存导入名称提示runtime/tmp/trivy/enriched_vulnerabilities.json:CVE 丰富输出runtime/tmp/semgrep/trigger_candidates.json:触发面候选runtime/tmp/semgrep/semgrep_results.md:人类可读的 Semgrep 触点摘要runtime/tmp/audit_report.md:最终 Markdown 报告runtime/logs/:工作流程和 Semgrep 日志
如果设置了 --export-audit-report,扫描器还会写入:
<target>/AUDIT_REPORT.md
- 优先选择分阶段证据优化而非一次性最终判断
- 将依赖存在、静态触点和可利用性视为不同问题
- 使用 Semgrep 进行触点筛选,而非证明可利用性
- 保留丰富的中间产物,以便结果可以被审计或移交给另一个代理
- 当前报告仍然是分类报告,不是完整的可利用性评估
- 运行时条件无法通过静态分析可靠确认
- 质量取决于所选模型、公告覆盖范围和目标代码库模式
- 某些特定于语言的启发式方法目前对 Python 的支持强于其他生态系统
最自然的下一步扩展是在 semgrep_scan 之后添加 agent_review 或 code_analysis 节点:
semgrep_scan -> agent_review -> audit_report
该节点可以使用结构化扫描结果并决定发现是否:
- 可利用
- 在实践中受保护或安全
- 仅运行时
- 需要手动审查
发布前添加您首选的许可证。