Autonomous CVE remediation — patches build files and source code, verifies the build, opens a PR
Project description
Sentinel — Autonomous CVE Remediation
Sentinel closes the "last mile" of CVE remediation.
Most tools tell you what's vulnerable. Sentinel fixes it — opening a verified, build-passing pull request with no human in the loop.
CVE detected → fork repo → resolve full dep tree → query OSV →
patch build files + source code → verify build in sandbox → open PR
Live demo PRs opened by Sentinel:
- Java: monitorjbl/excel-streaming-reader#271 — Log4Shell + Apache POI CVEs,
pom.xml+ Java source patched - Python: vulnerable-data-pipeline#2 — 5 PyPI CVEs,
requirements.txt+config.py+cache.pypatched
Install
pip install sentinel-remediation
Requires Docker running locally. Set credentials in a .env file (see Quick start).
Usage
# Fix CVEs in any public GitHub repo
sentinel fix-cve --repo https://github.com/org/repo
# Target a specific branch
sentinel fix-cve --repo https://github.com/org/repo --branch develop
# Force a specific LLM provider
sentinel fix-cve --repo https://github.com/org/repo --llm gemini
# Override the model
sentinel fix-cve --repo https://github.com/org/repo --llm anthropic --model claude-sonnet-4-6
Sentinel forks the repo, opens a sandbox container, scans, patches, verifies, and opens a PR — typically in under 3 minutes.
Why this is different
| Tool | Detects | Patches build file | Patches source code | Verifies build | Opens PR |
|---|---|---|---|---|---|
| Dependabot | ✅ | ✅ | ❌ | ❌ | ✅ |
| Snyk | ✅ | Partial | ❌ | ❌ | ✅ |
| Renovate | ✅ | ✅ | ❌ | ❌ | ✅ |
| Sentinel | ✅ | ✅ | ✅ | ✅ | ✅ |
Dependabot bumps versions. Sentinel bumps versions and fixes the dangerous call sites in your code — then proves the build still passes before touching your repo.
What Sentinel does
Three-layer remediation
Layer 1 — Transitive CVE detection
Resolves the complete dependency tree (not just declared deps) using the native build tool, then queries the OSV REST API for every package including transitively pulled dependencies. Catches CVEs that arrive silently through frameworks.
Layer 2 — Build file patching
LLM upgrades pom.xml, build.gradle, build.gradle.kts, gradle/libs.versions.toml, requirements.txt, and pyproject.toml to the minimum safe version. Handles version variables, BOM imports, Kotlin DSL, and Gradle version catalogs.
Layer 3 — Source code patching
Greps source files for dangerous call-site patterns — both CVE-specific and a built-in set of always-checked anti-patterns:
Python anti-patterns (always checked):
| Pattern | Risk |
|---|---|
yaml.load( |
RCE via unsafe deserialization |
pickle.loads( / pickle.load( |
RCE via deserialization |
Java anti-patterns (always checked):
| Pattern | Risk |
|---|---|
new ObjectInputStream( |
Java deserialization RCE |
Runtime.getRuntime().exec( |
OS command injection |
new ProcessBuilder( |
OS command injection |
MessageDigest.getInstance("MD5" |
Weak hashing |
MessageDigest.getInstance("SHA-1" |
Weak hashing |
new Random( |
Insecure randomness |
DocumentBuilderFactory.newInstance( |
XML External Entity (XXE) |
XMLInputFactory.newInstance( |
XML External Entity (XXE) |
PR audit trail
Every PR opened by Sentinel includes a structured evidence trail:
- CVEs addressed
- Files changed with patterns found
- Build verification status and attempt count
- Truncated build output (collapsible)
- Timestamp
Verify before merge
Every patch is tested in an isolated Docker sandbox (JDK 17 + Maven/Gradle, Python 3 + pip) before the PR is opened. If the build fails, Sentinel extracts the error, feeds it back to the LLM, and retries up to 3 times.
Fallback when PR can't be opened
If the GitHub API is unavailable or rate-limited, Sentinel extracts the diff from the container and saves it as sentinel-patch-<timestamp>.diff locally with apply instructions. The fix is never lost.
Supported ecosystems
| Build system | Detection | Transitive scan | Source patching | Verify command |
|---|---|---|---|---|
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 version catalog | ✅ | 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 |
Quick start
# 1. Install
pip install sentinel-remediation
# 2. Set credentials
cp .env.example .env
# Edit .env — add GITHUB_TOKEN and at least one LLM key:
# ANTHROPIC_API_KEY (Claude — recommended, best accuracy)
# GEMINI_API_KEY (Gemini Flash — cost-effective alternative)
# 3. Build the sandbox image (one-time, ~5 min)
docker build -t cve-fixer-sandbox:latest sandbox/
# 4. Run
sentinel fix-cve --repo https://github.com/anupamojha-eng/vulnerable-data-pipeline
Running via API (FastAPI server)
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"}'
Architecture
┌─────────────────────────────────────────────────────────┐
│ orchestrator/ │
│ │
│ cli.py `sentinel` CLI entry point │
│ driver.py FastAPI service — HTTP entry point │
│ 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 │
└─────────────────────────────────────────────────────────┘
│
│ 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 │
└─────────────────────────────────────────────────────────┘
Running tests
# Fast unit tests (no Docker, no API keys)
pytest tests/test_python_support.py tests/test_patching.py \
tests/test_build_detection.py tests/test_scanner.py -v
# Docker e2e — needs 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
# Full pipeline — needs 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
Technical stack
- CLI: Click —
sentinel fix-cve --repo <url> - Orchestrator: Python / FastAPI — container lifecycle, retry loop, 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 (fallback) - Reasoning: Multi-provider — Anthropic Claude (default) or Google Gemini
- Version control: PyGithub — fork, branch, commit, PR
LLM provider comparison
| Claude Opus 4.8 (default) | Gemini 2.5 Flash | |
|---|---|---|
| Complex multi-file patches | Excellent | Good |
| JSON output reliability | Excellent | Good |
| Prompt caching on retries | Yes (~80% savings) | No |
| Speed | Moderate | Fast |
| Cost per run | Higher | Lower |
Set ANTHROPIC_API_KEY for Claude, GEMINI_API_KEY for Gemini, or both (Claude wins when both set).
Override with ANTHROPIC_MODEL=claude-sonnet-4-6 or GEMINI_MODEL=gemini-2.5-pro.
Roadmap
-
sentinel fix-antipatterns— standalone anti-pattern fixing without a CVE trigger - Local LLM mode — Ollama + quantized model for air-gapped / zero-cost runs
- OSV offline cache — local SQLite built from OSV data dumps, no API calls
- Go (
go.mod) and Rust (Cargo.toml) ecosystem support - GitHub Actions integration — trigger on Dependabot alert webhook
- Container image scanning — pair with Chainguard Wolfi or distroless base images
Contributing
See CONTRIBUTING.md.
Security
See SECURITY.md for vulnerability disclosure policy.
License
Apache License 2.0 — see LICENSE.
Copyright 2026 Anupam Ojha
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sentinel_remediation-0.1.0.tar.gz.
File metadata
- Download URL: sentinel_remediation-0.1.0.tar.gz
- Upload date:
- Size: 53.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6a40a960a9418775944f290304f908fc4b21f2047dc5eaf20b084bad7e2dd6f
|
|
| MD5 |
1ac4792066af15b32809cbb37560c111
|
|
| BLAKE2b-256 |
be36825bf0dee47c9b774783156dcd47f76e33bae4ce271aa76cfd925a34416e
|
File details
Details for the file sentinel_remediation-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sentinel_remediation-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53cd2975698967da89e1cff1101ef014e0ca3046a42b1089682b78ae1e89e44d
|
|
| MD5 |
079eac4e35014a85b550b03e27799c32
|
|
| BLAKE2b-256 |
9ba528ce36cb8aeeec50facd11247911a37757f7713f36052cbf5ac34fcc748f
|