How to Give AI Coding Agents Real-Time CVE Auditing Without API Rate Limits: A Local MCP Vulnerability Scanner in Python
In 2026, autonomous software development agents (Claude Desktop, Cursor, Devin, Roo-Code) generate production code, scaffold microservices, and manage package dependencies across entire codebases.
However, giving autonomous agents the ability to install dependencies (pip install, npm install, cargo add) introduces a severe security hazard: AI agents frequently introduce critical known vulnerabilities (CVEs) into production applications.
π The Problem with Official CVE APIs: 5-Second Latency and Rate-Limit Walls
Why don't coding agents simply check every package against the National Vulnerability Database (NVD) or NIST before installing?
-
Brutal API Rate Limits: Without expensive commercial enterprise keys, NVD restricts requests to 5 calls every 30 seconds. An agent analyzing a moderate
requirements.txtwith 25 dependencies gets rate-limited for over 2 minutes. - High Latency & Downtime: Public vulnerability APIs frequently suffer 2-5 second round-trip latencies or server outages. When an LLM tool call hangs, the agent context times out.
- Alert Fatigue vs. Real Exploitation: Standard scanners report theoretical CVSS scores. A CVSS 7.5 vulnerability with 0.01% exploit probability triggers the same emergency alarm as a CISA KEV weaponized zero-day actively leveraged by ransomware gangs.
To solve this, we engineered CVESentry: an open Model Context Protocol (MCP) server in Python that executes sub-millisecond local SQLite WAL vulnerability lookups, supports multi-ecosystem parsing (Python, Node, Rust, Go), prioritizes threats using EPSS (Exploit Prediction Scoring System) and CISA KEV, and automatically produces safe SemVer upgrade patches.
ποΈ System Architecture
CVESentry runs as a high-speed local security sidecar communicating with your AI agent over stdio:
+-------------------------------------------------------------------------+
| AI Coding Agent (Claude / Cursor / Devin) |
+-------------------------------------------------------------------------+
|
(MCP JSON-RPC Tools)
v
+-------------------------------------------------------------------------+
| CVESentry MCP Server |
+-------------------------------------------------------------------------+
| | |
v v v
+-----------------+ +-----------------+ +-----------------+
| Multi-Ecosystem | | EPSS & CISA KEV | | Automated Safe |
| Manifest Parser | | Threat Engine | | Patch Generator |
| (Py/Node/Rust/Go| | (SQLite WAL) | | (SemVer Logic) |
+-----------------+ +-----------------+ +-----------------+
| | |
+-----------------------+-----------------------+
|
v
+-----------------------+
| SQLite WAL CVE Corpus |
| (<5ms local lookups) |
+-----------------------+
|
v
+------------------------------------------------+
| GitHub PR Markdown & JSON Compliance Report |
+------------------------------------------------+
1. Multi-Ecosystem Manifest Parsing
Different languages express dependencies with distinct syntax. CVESentry unifies manifest parsing across Python, Node, Rust, and Go:
import re
def parse_cargo_toml(content: str) -> list[dict]:
packages = []
in_deps = False
for line in content.splitlines():
line = line.strip()
if line.startswith("[") and "dependencies" in line.lower():
in_deps = True
continue
if in_deps and "=" in line:
pkg, val = [p.strip() for p in line.split("=", 1)]
ver_match = re.search(r'["\']([0-9.]+)["\']', val)
if ver_match:
packages.append({
"ecosystem": "cargo",
"package": pkg.lower(),
"version": ver_match.group(1)
})
return packages
2. Sub-Millisecond Local CVE Lookups in SQLite WAL
Instead of reaching out to external HTTP endpoints for every package, CVESentry maintains an indexed SQLite database in WAL mode:
import sqlite3
def find_vulnerabilities(conn: sqlite3.Connection, ecosystem: str, package: str, version: str):
rows = conn.execute("""
SELECT cve_id, affected_range, safe_version, cvss, severity, summary
FROM cve_records
WHERE ecosystem = ? AND LOWER(package) = LOWER(?);
""", (ecosystem, package)).fetchall()
vulnerable = []
for row in rows:
cve_id, affected_range, safe_version, cvss, sev, summary = row
if is_version_affected(version, affected_range):
vulnerable.append({
"cve_id": cve_id,
"cvss": cvss,
"severity": sev,
"safe_version": safe_version,
"summary": summary
})
return vulnerable
Looking up 50 packages takes under 4 millisecondsβallowing the agent to verify dependencies continuously during development without lag.
3. Exploit Probability (EPSS) & CISA KEV Prioritization
When an agent finds multiple vulnerabilities, how does it decide which to fix first?
CVESentry computes a Composite Threat Score:
$$\text{RiskScore} = \text{CVSS} \times (1.0 + \text{EPSS}) \times (\text{KEV Multiplier})$$
def calculate_composite_risk(cvss: float, epss_probability: float, in_cisa_kev: bool) -> dict:
multiplier = 1.5 if in_cisa_kev else 1.0
composite_score = round(cvss * (1.0 + epss_probability) * multiplier, 2)
if in_cisa_kev or composite_score >= 17.0:
priority = "P0_IMMEDIATE_HOTFIX"
action = "Active weaponization confirmed in CISA KEV catalog. Halt build."
elif composite_score >= 12.0:
priority = "P1_HIGH_PRIORITY"
action = "High probability of exploitation. Patch in current sprint."
else:
priority = "P2_MAINTENANCE"
action = "Standard update cycle."
return {
"composite_risk_score": composite_score,
"triage_priority": priority,
"action": action
}
For instance:
-
aiohttpwithCVE-2024-23334(CVSS 7.5, EPSS 78.2%, In CISA KEV) scores 20.05 (P0_IMMEDIATE_HOTFIX). -
requestswithCVE-2023-32681(CVSS 6.1, EPSS 5.4%, Not in KEV) scores 6.43 (P2_MAINTENANCE).
The agent focuses immediately on real threats rather than academic CVE noise.
4. Automated Safe Version Upgrading with Unified Diffs
Once a vulnerability is identified, CVESentry calculates the minimal SemVer upgrade to fix the flaw without breaking backwards compatibility:
import difflib
import re
def generate_safe_patch(requirements_content: str, fixes: dict) -> str:
original = requirements_content.splitlines(keepends=True)
patched = []
for line in original:
match = re.match(r"^([a-zA-Z0-9_\-\.]+)\s*(==|>=)\s*([0-9.]+)(.*)$", line)
if match:
pkg, op, ver, rest = match.groups()
if pkg.lower() in fixes:
patched.append(f"{pkg}>={fixes[pkg.lower()]}{rest}\n")
continue
patched.append(line)
diff = "".join(difflib.unified_diff(original, patched, fromfile="requirements.txt", tofile="requirements.txt"))
return diff
β‘ Integrating with Claude Desktop & Cursor
Add CVESentry to your claude_desktop_config.json:
{
"mcpServers": {
"cvesentry": {
"command": "python3",
"args": ["-m", "cvesentry.server"]
}
}
}
Now, prompt your agent:
"Audit this project's requirements.txt and package.json for active security threats. Prioritize any CISA KEV vulnerabilities and generate a safe patch."
Your agent inspects the code in milliseconds, triages threats by exploit probability, and updates your dependency tree with verified safe versions.
π Get Started: Open-Source & Enterprise
The open-source CVESentry Lite is available immediately on GitHub under the MIT license:
π GitHub Repository: https://github.com/johannschiffer/cvesentry-mcp
For enterprise development teams requiring multi-ecosystem support (Rust & Go), persistent SQLite WAL EPSS & CISA KEV threat intelligence, automated unified diff patchers, and complete Docker Compose manifests:
π Explore CVESentry Pro on Gumroad ($14.99 USD)
How do you prevent AI coding agents from introducing vulnerable dependencies in your development stack? Let's discuss in the comments below!
Top comments (0)