CVEHunt: Teaching LLMs to Exploit Vulnerabilities Without Breaking the Law
Hook
What happens when you ask GPT-4 to write an exploit for a real CVE? CVEHunt answers that question while preventing your AI assistant from becoming a criminal accomplice through localhost-only network boundaries baked into its DNA.
Context
Security researchers face a productivity paradox: analyzing whether a CVE is actually exploitable requires downloading vulnerable packages, diffing source code against patches, setting up isolated test environments, writing proof-of-concept code, and validating the attack vector—all manual work that takes hours per vulnerability. Meanwhile, CVE databases publish thousands of vulnerabilities monthly with varying severity scores that don't always correlate with real-world exploitability. A CVSS 9.8 critical vulnerability might be unexploitable in practice, while a 6.5 medium could lead to complete system compromise.
CVEHunt emerged as an experimental framework to automate this analysis pipeline using large language models as specialized agents. Rather than replacing human security researchers, it attempts to handle the mechanical grunt work: fetching package versions from npm and PyPI, generating unified diffs between vulnerable and patched code, scaffolding Docker-based test harnesses, and producing localhost-only proof-of-concept scripts. The twist? Every component includes hardcoded safety assertions that reject any network target outside 127.0.0.1, creating a system that can generate exploit code while maintaining ethical boundaries. It's a fascinating exploration of what happens when you weaponize LLM code generation capabilities while simultaneously constraining them through defensive architecture.
Technical Insight
CVEHunt's architecture centers on a sequential pipeline of seven specialized agents, each producing artifacts that feed the next stage. The workflow begins with the Collector agent parsing CVE metadata to identify affected package versions, then the Researcher agent downloads both vulnerable and patched releases from npm or PyPI registries. The HarnessBuilder creates isolated Docker environments for testing, the Exploiter generates proof-of-concept code, the FixDeveloper proposes patches, the Validator runs tests, and finally the Judge evaluates overall exploitability.
All artifacts persist in a file-based structure under cves/CVE-ID/runs/timestamp/ directories, effectively using the Git repository itself as a database. Each run contains diff.txt with source changes, harness.dockerfile for isolated environments, exploit.js or exploit.py for PoC code, and report.json with structured findings. This repository-as-database pattern means every analysis run becomes versioned history, and the React dashboard can statically generate a browsable interface by traversing these directories.
The most architecturally interesting aspect is how safety boundaries are enforced. Rather than relying on post-generation code review, CVEHunt embeds a SafetyPolicy module that performs static analysis on every generated exploit before execution:
class SafetyPolicy {
static validateExploit(code) {
// Reject any non-localhost network targets
const networkPatterns = [
/https?:\/\/(?!127\.0\.0\.1|localhost)/gi,
/connect\(['"](?!127\.0\.0\.1|localhost)/gi,
/socket\.connect\(['"][^'"]*(?<!127\.0\.0\.1|localhost)/gi
];
for (const pattern of networkPatterns) {
if (pattern.test(code)) {
throw new SafetyViolation(
'Exploit attempts to contact non-localhost target'
);
}
}
// Ensure Docker harness has no network access
if (!code.includes('--network=none') &&
code.includes('docker run')) {
throw new SafetyViolation(
'Docker harness must run with --network=none'
);
}
return true;
}
}
This defensive layering means even if an LLM hallucinates malicious network calls, the safety policy intercepts them before execution. The system literally cannot attack external targets without code modifications that would be obvious in version control.
The multi-model support is implemented through a pluggable backend abstraction that normalizes API calls across OpenAI, Anthropic, and Google endpoints. Each agent execution records which model generated its outputs, creating an audit trail of AI-generated artifacts:
const runAgent = async (agentName, context, options = {}) => {
const model = options.model || process.env.DEFAULT_MODEL;
const prompt = buildPrompt(agentName, context);
const response = await llmBackend.complete({
model,
messages: [{ role: 'user', content: prompt }],
temperature: 0.2 // Lower temperature for deterministic output
});
const artifact = {
agent: agentName,
model: model,
timestamp: new Date().toISOString(),
input: context,
output: response.content
};
await saveArtifact(artifact);
return artifact.output;
};
The temperature is deliberately set low (0.2) for exploit generation to reduce creative hallucinations—you want deterministic, working exploit code, not creative variations that might bypass safety checks.
Package diffing happens through a surprisingly straightforward approach: download both versions from registry APIs, extract tarballs, run diff -ur between directories, and feed the unified diff to the LLM. For npm packages, it queries the registry API at https://registry.npmjs.org/package-name to find version manifests, downloads tarballs, and compares. PyPI works similarly through the JSON API at https://pypi.org/pypi/package-name/json. The diff output becomes the primary signal for the Exploiter agent to understand what changed between vulnerable and patched versions.
The React dashboard generation is pure static site generation—it walks the cves/ directory tree, parses JSON artifacts, and renders them into a Vite-built SPA deployed to GitHub Pages. No backend server required, just versioned files and client-side JavaScript that loads them on-demand.
Gotcha
The elephant in the room is ecosystem support: CVEHunt only handles npm and PyPI packages. If your CVE affects Go modules, Ruby gems, Maven artifacts, Cargo crates, or any other package ecosystem, you're out of luck. The entire package download and diff generation logic is hardcoded for these two registries, and extending support requires implementing registry-specific APIs, tarball extraction logic, and dependency resolution for each new ecosystem. For a tool claiming to automate CVE analysis, covering only two ecosystems severely limits practical utility.
The safety boundaries, while clever, rely on regex pattern matching against generated code—a notoriously fragile approach. A sufficiently sophisticated LLM output could bypass these checks through indirection: storing target IPs in environment variables, constructing URLs character-by-character to avoid regex detection, or using DNS rebinding techniques where localhost resolves to external IPs. The SafetyPolicy provides defense-in-depth against accidental external attacks, but shouldn't be considered a security guarantee against adversarial prompt injection. Additionally, the project has exactly one GitHub star and appears to be a solo developer experiment with no evidence of production usage, battle-testing, or community validation. Treat this as an interesting proof-of-concept for exploring LLM-driven security automation concepts rather than production-ready tooling.
Verdict
Use CVEHunt if you're researching automated vulnerability analysis workflows, want hands-on experience with multi-agent LLM systems in a security context, or need a framework for safely studying CVE exploitability in npm/PyPI ecosystems without ethical concerns. The repository-as-database pattern and hardcoded safety boundaries make it an excellent educational tool for understanding how to constrain LLM outputs in sensitive domains. Skip if you need production vulnerability scanning, support for ecosystems beyond JavaScript and Python, or battle-tested security tooling with community validation. This is clearly experimental research code from a solo developer exploring agentic AI concepts—intellectually fascinating for security researchers and AI engineers, but not ready to replace Metasploit or Snyk in your actual security workflows.