DEV Community

johann
johann

Posted on

How to Give AI Coding Agents Real-Time CVE Auditing Without API Rate Limits: A Local MCP Vulnerability Scanner in Python

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?

  1. Brutal API Rate Limits: Without expensive commercial enterprise keys, NVD restricts requests to 5 calls every 30 seconds. An agent analyzing a moderate requirements.txt with 25 dependencies gets rate-limited for over 2 minutes.
  2. 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.
  3. 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  |
        +------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
    }
Enter fullscreen mode Exit fullscreen mode

For instance:

  • aiohttp with CVE-2024-23334 (CVSS 7.5, EPSS 78.2%, In CISA KEV) scores 20.05 (P0_IMMEDIATE_HOTFIX).
  • requests with CVE-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
Enter fullscreen mode Exit fullscreen mode

⚑ Integrating with Claude Desktop & Cursor

Add CVESentry to your claude_desktop_config.json:

{
  "mcpServers": {
    "cvesentry": {
      "command": "python3",
      "args": ["-m", "cvesentry.server"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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)