anupamojha-eng/agentic-remediation-factory

GitHub: anupamojha-eng/agentic-remediation-factory

Sentinel 是一款自主式 CVE 漏洞修复工具,能自动修补构建文件与源代码、在 Docker 沙箱中验证构建并提交修复 PR。

Stars: 0 | Forks: 0

# Sentinel — 自主 CVE 修复 [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/) [![PyPI](https://img.shields.io/pypi/v/sentinel-remediation.svg)](https://pypi.org/project/sentinel-remediation/) [![Ecosystems](https://img.shields.io/badge/ecosystems-Java%20%7C%20Python-green.svg)](#supported-ecosystems) **Sentinel 打通了 CVE 修复的“最后一公里”。** 大多数工具只会告诉你哪里有漏洞。Sentinel 则会修复它 —— 在无需人工干预的情况下,开启一个经过验证且通过构建的 pull request。 ``` CVE detected → fork repo → resolve full dep tree → query OSV → patch build files + source code → verify build in sandbox → open PR ``` **Sentinel 开启的实时演示 PR:** - Java: [monitorjbl/excel-streaming-reader#271](https://github.com/monitorjbl/excel-streaming-reader/pull/271) — Log4Shell + Apache POI CVE,修补了 `pom.xml` + Java 源码 - Python: [vulnerable-data-pipeline#2](https://github.com/anupamojha-eng/vulnerable-data-pipeline/pull/2) — 5 个 PyPI CVE,修补了 `requirements.txt` + `config.py` + `cache.py` ## 安装说明 ``` pip install sentinel-remediation ``` 需要在本地运行 Docker。在 `.env` 文件中设置凭证(参见[快速开始](#quick-start))。 ## 用法 ### 修复单个仓库中的 CVE ``` # 修复任何公开 GitHub repo 中的 CVE sentinel fix-cve --repo https://github.com/org/repo # 针对特定 branch sentinel fix-cve --repo https://github.com/org/repo --branch develop # 强制使用特定 LLM provider sentinel fix-cve --repo https://github.com/org/repo --llm gemini # 覆盖 model sentinel fix-cve --repo https://github.com/org/repo --llm anthropic --model claude-sonnet-4-6 ``` Sentinel 会 fork 该仓库,开启一个 sandbox 容器,执行扫描、修补、验证,并开启一个 PR —— 通常在 3 分钟内完成。 ### 扫描整个 GitHub 组织 ``` # 扫描所有 repo — 生成 HTML 报告,不创建 PR(默认安全) sentinel scan-org --org my-org # 按 severity 和语言过滤 sentinel scan-org --org my-org --severity CRITICAL HIGH --language java python # 将范围限定为匹配特定 pattern 的 repo sentinel scan-org --org my-org --include "platform-*" --exclude "*-test" # 扫描所有 CRITICAL 发现并创建修复 PR sentinel scan-org --org my-org --severity CRITICAL --create-prs # 将报告保存到特定路径,同时输出 JSON sentinel scan-org --org my-org --report security-report.html --json-out results.json # GitHub Enterprise sentinel scan-org --org my-org --github-url https://github.mycompany.com/api/v3 ``` `scan-org` **默认以 dry-run 模式运行** —— 它会扫描每个仓库并生成报告,但不会触及任何代码或开启任何 PR。传递 `--create-prs` 参数以启用完整修复。 HTML 报告会显示: - 摘要:已扫描的仓库、受影响的仓库、按严重程度划分的 CVE、已创建的 PR - 各仓库的 CVE 表格,包含 advisory ID、受影响的包、修复版本 - 干净的仓库列表 - 任何扫描错误 ## 为什么与众不同 | 工具 | 检测漏洞 | 修补构建文件 | 修补源代码 | 验证构建 | 开启 PR | |---|---|---|---|---|---| | Dependabot | ✅ | ✅ | ❌ | ❌ | ✅ | | Snyk | ✅ | 部分 | ❌ | ❌ | ✅ | | Renovate | ✅ | ✅ | ❌ | ❌ | ✅ | | **Sentinel** | ✅ | ✅ | ✅ | ✅ | ✅ | Dependabot 只会升级版本。Sentinel 不仅升级版本,*还*会修复代码中危险的调用点 —— 然后在触及你的仓库之前证明构建仍然通过。 ## Sentinel 的功能 ### 三层修复 **第一层 — 传递性 CVE 检测** 使用原生构建工具解析*完整*的依赖树(不仅仅是已声明的依赖),然后针对每个包(包括传递依赖)查询 OSV REST API。捕获那些通过框架悄悄引入的 CVE。 **第二层 — 构建文件修补** LLM 将 `pom.xml`、`build.gradle`、`build.gradle.kts`、`gradle/libs.versions.toml`、`requirements.txt` 和 `pyproject.toml` 升级到最低安全版本。处理版本变量、BOM 导入、Kotlin DSL 和 Gradle 版本目录。 **第三层 — 源代码修补** 通过 grep 在源文件中搜索危险的调用点模式 —— 包括特定于 CVE 的模式和一组始终检查的内置反模式: **Python 反模式(始终检查):** | 模式 | 风险 | |---------|------| | `yaml.load(` | 通过不安全的反序列化引发 RCE | | `pickle.loads(` / `pickle.load(` | 通过反序列化引发 RCE | **Java 反模式(始终检查):** | 模式 | 风险 | |---------|------| | `new ObjectInputStream(` | Java 反序列化 RCE | | `Runtime.getRuntime().exec(` | OS 命令注入 | | `new ProcessBuilder(` | OS 命令注入 | | `MessageDigest.getInstance("MD5"` | 弱哈希 | | `MessageDigest.getInstance("SHA-1"` | 弱哈希 | | `new Random(` | 不安全的随机性 | | `DocumentBuilderFactory.newInstance(` | XML External Entity (XXE) | | `XMLInputFactory.newInstance(` | XML External Entity (XXE) | ### PR 审计追踪 Sentinel 开启的每个 PR 都包含一条结构化的证据链: - 处理的 CVE - 发生变更的文件及其匹配到的模式 - 构建验证状态和尝试次数 - 截断的构建输出(可折叠) - 时间戳 ### 合并前验证 在开启 PR 之前,每个补丁都会在一个隔离的 Docker sandbox(JDK 17 + Maven/Gradle,Python 3 + pip)中进行测试。如果构建失败,Sentinel 会提取错误,将其反馈给 LLM,并最多重试 3 次。 ### 无法开启 PR 时的兜底方案 如果 GitHub API 不可用或受到速率限制,Sentinel 会从容器中提取 diff 并将其作为 `sentinel-patch-.diff` 在本地保存,同时附带应用说明。修复内容永远不会丢失。 ## 支持的生态系统 | 构建系统 | 检测 | 传递性扫描 | 源代码修补 | 验证命令 | |---|---|---|---|---| | Maven (`pom.xml`) | ✅ | `mvn dependency:list` | ✅ `.java` | `mvn clean compile` | | Gradle Groovy | ✅ | `gradle dependencies` | ✅ `.java` | `gradle compileJava` | | Gradle KTS | ✅ | `gradle dependencies` | ✅ `.java` | `gradle compileJava` | | Gradle 版本目录 | ✅ | `gradle dependencies` | ✅ `.java` | `gradle compileJava` | | `requirements.txt` | ✅ | `pip install` + `pip list` | ✅ `.py` | `pip install && pytest` | | `pyproject.toml` | ✅ | `pip install` + `pip list` | ✅ `.py` | `pip install && pytest` | ## 快速开始 ``` # 1. 安装 pip install sentinel-remediation # 2. 设置 credentials cp .env.example .env # 编辑 .env — 添加 GITHUB_TOKEN 和至少一个 LLM key: # ANTHROPIC_API_KEY (Claude — 推荐,准确率最高) # GEMINI_API_KEY (Gemini Flash — 高性价比替代方案) # 3. 构建 sandbox image(一次性,约 5 分钟) docker build -t cve-fixer-sandbox:latest sandbox/ # 4. 运行 sentinel fix-cve --repo https://github.com/anupamojha-eng/vulnerable-data-pipeline ``` ### 通过 API 运行(FastAPI 服务器) ``` python3 orchestrator/driver.py # starts on :8080 curl -X POST http://localhost:8080/remediate \ -H "Content-Type: application/json" \ -d '{"repo_url": "https://github.com/org/repo", "target_tag": "main"}' ``` ## 架构 ``` ┌─────────────────────────────────────────────────────────┐ │ orchestrator/ │ │ │ │ cli.py `sentinel` CLI — fix-cve + scan-org │ │ driver.py FastAPI service — HTTP entry point │ │ │ │ org_scanner.py OrgScanner │ │ ├─ scan() iterate repos → quick scan │ │ ├─ _detect_and_extract_deps() GitHub contents API │ │ ├─ _query_osv() OSV batch API, severity map │ │ └─ create_prs_for_results() delegate to factory │ │ │ │ report.py ReportGenerator │ │ ├─ generate_html() professional HTML report │ │ └─ generate_json() machine-readable JSON output │ │ │ │ factory.py RemediationFactory │ │ ├─ _detect_build_system() Maven/Gradle/Python │ │ ├─ _scan_internal() resolve deps → OSV API │ │ │ └─ _scan_with_osv_scanner() fallback │ │ ├─ _get_verify_command() build tool selector │ │ └─ retry loop (MAX=3) smart error routing │ │ │ │ remediator.py RemediationActor │ │ ├─ get_vulnerable_code_files() grep → source files │ │ ├─ get_affected_java_files() parse compile errors │ │ ├─ autonomous_patch() LLM → write → verify │ │ ├─ create_pull_request() branch → push → PR │ │ ├─ _build_pr_body() audit trail │ │ └─ _patch_fallback() save diff locally │ │ │ │ llm_client.py SecurityAgentClient │ │ ├─ _AnthropicProvider Claude Opus 4.8 (default) │ │ ├─ _GeminiProvider Gemini 2.5 Flash (alt) │ │ ├─ get_vulnerable_patterns() CVE → grep strings │ │ └─ get_remediation_plan() full patch plan │ │ │ │ telemetry.py Observability │ │ ├─ setup_telemetry() OTLP or console export │ │ ├─ TokenUsageTracker per-run token + cost report │ │ └─ record_llm_tokens() OTel counters + cost tracker │ └─────────────────────────────────────────────────────────┘ │ │ Docker SDK ▼ ┌─────────────────────────────────────────────────────────┐ │ sandbox/ (Docker image) │ │ │ │ JDK 17 · Maven 3.9 · Gradle 9.4 · OSV-Scanner │ │ Python 3 · pip3 · git │ │ │ │ Isolated per-run: no shared state between remediations │ └─────────────────────────────────────────────────────────┘ ``` ## 运行测试 ``` # 快速 unit test(无需 Docker,无需 API key) pytest tests/test_python_support.py tests/test_patching.py \ tests/test_build_detection.py tests/test_scanner.py -v # Docker e2e — 需要 Docker + LLM key pytest tests/test_e2e_docker.py -v -s # Java pytest tests/test_e2e_python_docker.py -v -s # Python # Source patching e2e pytest tests/test_java_source_patching_e2e.py -v -s pytest tests/test_python_source_patching_e2e.py -v -s # 完整 pipeline — 需要 Docker + LLM key + GITHUB_TOKEN pytest tests/test_real_repo_e2e.py -v -s # Java pytest tests/test_real_python_repo_e2e.py -v -s # Python ``` ## 可观测性 每次运行都会发出 OTel traces 和 metrics。设置 `OTEL_EXPORTER_OTLP_ENDPOINT` 以将其发送到任何后端(Grafana、Datadog、Honeycomb)。如果未设置,则默认输出到控制台。 ### Traces | Span | Attributes | |------|-----------| | `sentinel.remediation` | `repo`, `branch`, `build_system`, `cve_count`, `pr_url` | | `sentinel.scan` | `cve_count`, `cves` | | `sentinel.patch` | `attempt` | | `sentinel.llm_call` | `stage`, `model` | | `sentinel.verify` | `attempt`, `exit_code` | | `sentinel.pr_create` | `pr_url`, `success` | ### Metrics | Metric | 类型 | 标签 | |--------|------|------| | `sentinel.remediation_duration_seconds` | histogram | `build_system` | | `sentinel.scan_duration_seconds` | histogram | `build_system` | | `sentinel.verify_duration_seconds` | histogram | `build_system`, `attempt` | | `sentinel.cves_found_total` | counter | `build_system` | | `sentinel.patch_attempts_total` | counter | `build_system`, `attempt` | | `sentinel.pr_opened_total` | counter | `build_system`, `success` | | `sentinel.llm_tokens_total` | counter | `model`, `stage`, `repo`, `type` | | `sentinel.llm_cost_usd_total` | counter | `model`, `stage`, `repo` | ### Token 及成本报告 在每次运行结束时打印 —— 显示各阶段的 token 使用量、cache 命中情况、节省的 cache 成本(美元)以及总成本: ``` ════════════════════════════════════════════════════════════════════════════════ Sentinel Token & Cost Report Repo: https://github.com/org/repo ════════════════════════════════════════════════════════════════════════════════ Stage Model In Out Cache↓ Cache↑ Cost ────────────────────────────────────────────────────────────────────────────── pattern_detect claude-opus-4-8 1,234 89 — — $0.0185 patch claude-opus-4-8 12,456 823 — 8,234 $0.0234 cache saved: -$0.1235 ────────────────────────────────────────────────────────────────────────────── TOTAL 13,690 912 — 8,234 $0.0419 Cache savings:.................................... -$0.1235 Net cost (after savings):......................... $0.0419 ════════════════════════════════════════════════════════════════════════════════ ``` Cache↓ = 从 cache 读取的 token · Cache↑ = 写入 cache 的 token ## 技术栈 - **CLI**: Click — `sentinel fix-cve --repo ` - **Orchestrator**: Python / FastAPI — 容器生命周期、重试循环、GitHub API - **Sandbox**: Docker(JDK 17、Maven 3.9.15、Gradle 9.4.1、OSV-Scanner、Python 3 + pip) - **Scanning**: `mvn dependency:list` / `gradle dependencies` / `pip list` + OSV REST API;OSV-Scanner(兜底) - **Reasoning**: 多提供商 — Anthropic Claude(默认)或 Google Gemini - **Version control**: PyGithub — fork、branch、commit、PR ### LLM 提供商对比 | | Claude Opus 4.8(默认) | Gemini 2.5 Flash | |---|---|---| | 复杂的多文件补丁 | 优秀 | 良好 | | JSON 输出可靠性 | 优秀 | 良好 | | 重试时的 prompt caching | 是(节省约 80%) | 否 | | 速度 | 中等 | 快 | | 单次运行成本 | 较高 | 较低 | 为 Claude 设置 `ANTHROPIC_API_KEY`,为 Gemini 设置 `GEMINI_API_KEY`,或者同时设置两者(同时设置时 Claude 优先)。 使用 `ANTHROPIC_MODEL=claude-sonnet-4-6` 或 `GEMINI_MODEL=gemini-2.5-pro` 进行覆盖。 ## 微调的本地模型(路线图) 长期目标是打造一个 `sentinel-patcher` 模型 —— 一个专门针对 CVE 修补进行微调的小型量化模型 —— 直接嵌入到 Docker sandbox 镜像中。这消除了所有的外部 API 调用,并使 Sentinel 能够完全在气隙环境下运行。 ### MLOps pipeline ``` ┌──────────────────────────────────────────────────────────────────────┐ │ DATA COLLECTION built ✅ │ │ │ │ training/collect_osv.py OSV data dumps (Maven + PyPI) │ │ └─ synthetic pairs: vulnerable build file → patched file │ │ │ │ training/collect_github.py GitHub security fix PRs │ │ └─ real before/after diffs from merged security PRs │ │ │ │ training/sentinel_logger.py Self-improvement loop │ │ └─ every verified Sentinel run → appended to train set │ │ │ │ All output → training/data/train.jsonl (chat JSONL format) │ └──────────────────────────┬───────────────────────────────────────────┘ │ ~4,000+ examples ▼ ┌──────────────────────────────────────────────────────────────────────┐ │ FINE-TUNING built ✅ │ │ │ │ training/train.py Unsloth QLoRA on Qwen2.5-Coder-7B │ │ └─ runs anywhere with GPU: Colab, Modal, RunPod │ │ └─ exports Q4_K_M GGUF (~4GB) │ │ └─ pushes to Hugging Face Hub │ │ │ │ training/train_modal.py Serverless GPU wrapper │ │ └─ modal run training/train_modal.py │ │ └─ spins up A100 on demand (~$5/run, ~30 min) │ │ └─ tears down automatically when done │ │ │ │ Triggered by: retrain.yml GitHub Actions │ │ └─ on push to sentinel_self.jsonl (new verified patches) │ │ └─ weekly cron (Sunday 2am UTC, fresh OSV data) │ │ └─ manually via workflow_dispatch │ └──────────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────────┐ │ EVALUATION (CI QUALITY GATE) built ✅ │ │ │ │ training/evaluate.py runs inference on held-out eval.jsonl │ │ │ │ Scores each prediction on 5 dimensions: │ │ json_valid output parses as valid JSON │ │ schema_valid patches / changes / analysis keys present │ │ files_match all expected files patched │ │ version_correct fixed version present, vulnerable version gone │ │ no_regression non-security lines preserved unchanged │ │ │ │ pass@1 = all 5 pass threshold: 80% │ │ │ │ GitHub Actions runs this on every model update + weekly schedule │ │ CI fails if pass@1 < threshold → previous model kept │ └──────────────┬───────────────────────────┬──────────────────────────┘ │ pass ✅ │ fail ❌ ▼ ▼ ┌──────────────────────────────┐ ┌────────────────────────────────┐ │ DEPLOY planned⏳│ │ ALERT │ │ │ │ │ │ Published to HF Hub: │ │ CI fails, previous model kept │ │ anupamojha/sentinel-patcher │ └────────────────────────────────┘ │ │ │ retrain.yml rebuilds Docker │ │ image with new model ref │ │ │ │ Uses llama.cpp server at │ │ localhost:8080 — zero │ │ external API calls │ └──────────────────────────────┘ │ ▼ feedback ┌──────────────────────────────────────────────────────────────────────┐ │ SELF-IMPROVEMENT LOOP built ✅ │ │ │ │ Set SENTINEL_TRAINING_LOG=training/data/sentinel_self.jsonl │ │ Every verified patch (build passes) → appended to training data │ │ When dataset grows by 500+ examples → trigger fine-tuning again │ │ │ │ Model improves on the exact CVEs it encounters in production │ └──────────────────────────────────────────────────────────────────────┘ ``` ### 如今运行该 pipeline ``` # 1. 收集训练数据(来自 OSV + GitHub 的约 4,000 个示例) python training/collect_osv.py --ecosystems Maven PyPI --limit 2000 \ --out training/data/osv.jsonl GITHUB_TOKEN=... python training/collect_github.py --limit 200 \ --out training/data/github.jsonl # 2. 拆分为 train / eval python training/evaluate.py --split training/data/osv.jsonl \ --eval-out training/data/eval.jsonl \ --train-out training/data/train.jsonl # 3a. 本地训练(需要 GPU — Google Colab 或类似环境) HF_TOKEN=... python training/train.py \ --data training/data/train.jsonl \ --hf-repo anupamojha/sentinel-patcher-7b \ --push-to-hub # 3b. 在 Modal cloud GPU 上训练(约 $5,A100,约 30 分钟 — 无需本地 GPU) pip install modal && modal setup modal run training/train_modal.py \ --hf-repo anupamojha/sentinel-patcher-7b # 4. 评估 model 质量(CI gate) ANTHROPIC_API_KEY=... python training/evaluate.py \ --eval-set training/data/eval.jsonl \ --provider anthropic --threshold 0.75 # 5. 在生产 run 中启用自我改进 SENTINEL_TRAINING_LOG=training/data/sentinel_self.jsonl \ sentinel fix-cve --repo https://github.com/org/repo ``` **CI 工作流:** - `.github/workflows/model-eval.yml` — 每次推送到 `training/` 时运行评估,每周一次 - `.github/workflows/retrain.yml` — 当 `sentinel_self.jsonl` 增加或每周一次时触发完整重新训练;需要在 GitHub 中配置 `MODAL_TOKEN_ID`、`MODAL_TOKEN_SECRET`、`HF_TOKEN` secrets ## 路线图 - [ ] 通过 llama.cpp 服务器将模型嵌入到 Docker sandbox 镜像中(已构建 train.py + train_modal.py) - [ ] 将 `SENTINEL_LOCAL_MODEL` 环境变量作为第三个提供商接入 llm_client.py - [ ] `sentinel fix-antipatterns` — 独立的反模式修复,无需 CVE 触发 - [ ] OSV 离线 cache —— 从 OSV 数据转储构建的本地 SQLite,无需 API 调用 - [ ] Go (`go.mod`) 和 Rust (`Cargo.toml`) 生态系统支持 - [ ] GitHub Actions 集成 —— 在 Dependabot 告警 webhook 上触发 - [ ] 容器镜像扫描 —— 与 Chainguard Wolfi 或 distroless 基础镜像搭配使用 ## 安全 有关漏洞披露政策,请参见 [SECURITY.md](SECURITY.md)。 ## 许可证 Apache License 2.0 — 详见 [LICENSE](LICENSE)。 版权所有 2026 Anupam Ojha
标签:AI编程助手, DevSecOps, GPT, 上游代理, 代码修复, 依赖更新, 后台面板检测, 模块化设计, 漏洞管理, 用户代理, 自动化修复, 请求拦截, 逆向工具