| name | multi-agent-end-to-end-vulnerability-management |
| description | Detect, confirm, repair, and validate recurring software vulnerabilities using a multi-agent pipeline modeled on MAVM. Builds a vulnerability knowledge base from historical CVE/patch data, then coordinates specialized agents for detection, confirmation, repair, and validation. Trigger phrases: 'find recurring vulnerabilities', 'scan for known vulnerability patterns', 'port security patches across repos', 'detect unpatched code clones', 'end-to-end vulnerability management', 'fix recurring security issues'. |
Multi-Agent End-to-End Vulnerability Management
This skill enables Claude to perform end-to-end recurring vulnerability management on codebases by applying the MAVM (Multi-Agent Vulnerability Management) pipeline from Zheng et al. The technique coordinates five stages — knowledge base construction, detection, confirmation, repair, and validation — to find code that replicates known vulnerabilities (through code reuse, forking, or shared logic), confirm they are genuine, generate context-aware patches, and verify correctness. Unlike single-pass static analysis or naive LLM prompting, this approach retrieves repository-level context across function and module boundaries and grounds every decision in historical vulnerability knowledge.
When to Use
- When the user asks to scan a codebase for known vulnerability patterns (e.g., "check if any of these CVEs affect my fork")
- When porting security patches from an upstream project to a downstream fork or branch
- When investigating whether a disclosed CVE in one project affects a related project that shares code
- When the user wants to detect unpatched code clones of known vulnerable functions
- When performing a systematic security audit against a set of historical CVEs
- When the user asks to repair a recurring vulnerability and needs the fix validated
- When analyzing whether a patch from one repository can be adapted to another repository's codebase
Key Technique
Recurring vulnerabilities are security flaws that reappear across codebases due to code cloning, forking, copy-paste reuse, or shared upstream libraries. MAVM addresses these by constructing a Vulnerability Knowledge Base (VKB) from publicly disclosed CVEs. For each CVE, the VKB stores: the CVE description and CWE category, the root cause analysis, the vulnerability trigger chain (the sequence of logic states and execution conditions that activate the flaw), the original patch, and distilled analysis points — diagnostic heuristics that define the specific conditions an analyst must check to confirm the vulnerability's presence in new code.
The pipeline then operates in four agent-driven stages. The Detection stage uses syntax-based clone detection (ReDeBug-style pattern matching) combined with hash-based function similarity to identify candidate vulnerable functions in the target repository — taking the union of both methods to maximize recall. The Confirmation stage uses a Porting Agent to adapt the VKB's analysis points from the original repository's context to the target repository's context (accounting for renamed functions, different structures, missing dependencies), then an Analyzing Agent walks through each analysis point against the candidate function, using context-retrieval tools to pull in cross-function and cross-module information. Only confirmed true positives proceed to the Repair stage, where a Fixing Agent generates patches informed by the historical patch, the confirmation analysis, and a consistency check that finds semantically equivalent substitute functions when the target repo lacks exact counterparts. Finally, the Validation stage re-runs detection on the patched code and applies the same analysis-point reasoning to verify the fix eliminated the vulnerability without introducing regressions.
The critical insight is that historical vulnerability knowledge (analysis points, root causes, patches) dramatically reduces false positives and improves repair accuracy when combined with repository-level context retrieval — achieving 31.9%-45.2% higher repair accuracy than baselines.
Step-by-Step Workflow
-
Build the vulnerability knowledge base entry. For the target CVE(s), collect: CVE ID, CWE category, CVE description, the original vulnerable code, the patch commit, and the commit message. Analyze the root cause, identify the trigger chain (what sequence of conditions activates the flaw), and distill 3-6 concrete analysis points — specific logical checks that determine whether a given function instance is vulnerable.
-
Identify the target codebase and scope. Determine which repository, branch, or fork to scan. Establish the relationship to the original vulnerable project (direct fork, shared upstream, copy-pasted module, etc.). Map the relevant source directories.
-
Run clone-based detection. Search the target codebase for functions with high syntactic similarity to the known vulnerable function. Use code search (grep/ripgrep for distinctive code patterns, function signatures, or unique string literals from the vulnerable code) and structural matching (compare function bodies, control flow patterns, and API call sequences). Flag all candidate functions that share substantial code with the vulnerable original.
-
Run hash/similarity-based detection. Independently identify functions whose overall structure (normalized token sequences, key operations, variable usage patterns) closely matches the vulnerable function. Take the union of results from steps 3 and 4 to form the candidate set.
-
Port analysis points to the target context. For each candidate function, adapt the VKB analysis points to the target repository's naming conventions, data structures, and API surface. Use context-retrieval — read related function definitions, struct/class declarations, call sites, and header files — to understand how the target code maps to the original. If the target repository uses different function names for equivalent operations, note the mapping.
-
Confirm each candidate. Walk through every ported analysis point against the candidate function. For each point, determine whether the vulnerable condition holds in the target context. Retrieve cross-function context (callers, callees, global state) as needed. If the target implementation diverges from the original in a way that neutralizes the vulnerability (e.g., added bounds check, different control flow), mark it as a false positive. Only confirmed vulnerabilities proceed.
-
Check consistency for repair. For each confirmed vulnerability, compare the target function's dependencies against the original patch's requirements. Identify any functions, types, or macros referenced by the patch that do not exist in the target repository. For each missing dependency, search for a semantically equivalent substitute in the target codebase.
Concrete Examples
Example 1: Detecting a buffer overflow clone in a fork
User: "CVE-2024-1234 was fixed in upstream libfoo. Check if our fork
(in ./vendor/libfoo-fork/) is still vulnerable."
Approach:
1. Read the upstream CVE patch commit. Identify the vulnerable function
`parse_header()` in `src/parser.c` — a heap buffer overflow caused
by missing length validation before memcpy on line 247.
2. Build analysis points:
- AP1: Does `parse_header()` validate `hdr->length` against buffer
capacity before the memcpy call?
- AP2: Is `buf` allocated with a fixed size that can be exceeded
by attacker-controlled `hdr->length`?
- AP3: Is there any caller-side validation that bounds `hdr->length`?
3. Search ./vendor/libfoo-fork/src/ for `parse_header` — found in
`parser.c:231` with near-identical implementation.
4. Port analysis points: function and variable names match exactly.
5. Confirm: AP1 — no length validation before memcpy (line 245). AP2 —
buf is stack-allocated at 256 bytes, hdr->length is unchecked.
AP3 — callers pass raw network input. CONFIRMED VULNERABLE.
6. Generate patch: add `if (hdr->length > sizeof(buf)) return -1;`
before the memcpy, matching the upstream fix.
7. Validate: re-check patched function — AP1 now satisfied, memcpy is
bounded. Patch is correct.
Output:
VULNERABILITY CONFIRMED: CVE-2024-1234
File: vendor/libfoo-fork/src/parser.c
Function: parse_header() (line 231)
Root cause: Missing bounds check on hdr->length before memcpy
Status: Patch generated and validated
--- a/vendor/libfoo-fork/src/parser.c
+++ b/vendor/libfoo-fork/src/parser.c
@@ -243,6 +243,8 @@
struct header *hdr = raw_input;
char buf[256];
+ if (hdr->length > sizeof(buf))
+ return -EINVAL;
memcpy(buf, hdr->data, hdr->length);
Example 2: Cross-project patch porting (Vim to Neovim)
User: "CVE-2025-5678 was patched in Vim. Does Neovim have the same
use-after-free in its undo handling?"
Approach:
1. Retrieve Vim's patch for CVE-2025-5678. The fix is in `undo.c`,
function `u_freeentry()` — a use-after-free where `ue->ue_next`
is accessed after `free(ue)`.
2. Build analysis points:
- AP1: Is the undo entry freed before its `next` pointer is read?
- AP2: Is there a local variable caching `ue->ue_next` before free?
- AP3: Does the loop structure allow the freed pointer dereference?
3. Search Neovim's src/nvim/ for u_freeentry or equivalent undo-free
logic. Found `u_freeentry()` in `undo.c:1847` — structurally
similar but uses Neovim's memory allocator `xfree()` instead of
`vim_free()`.
4. Port analysis points: substitute `xfree` for `vim_free`, confirm
`ue_next` field exists in Neovim's undo entry struct (it does,
same name).
5. Confirm: AP1 — yes, `xfree(ue)` on line 1853, then `ue->ue_next`
on line 1854. AP2 — no caching variable. CONFIRMED VULNERABLE.
6. Consistency check: Vim's patch uses `vim_free()`, Neovim uses
`xfree()` — direct semantic equivalent found.
7. Generate patch: cache `ue->ue_next` in a local variable before
the `xfree(ue)` call, then use the cached pointer.
8. Validate: AP1 no longer holds — freed pointer is not dereferenced.
Output:
VULNERABILITY CONFIRMED: CVE-2025-5678 (ported from Vim)
File: src/nvim/undo.c
Function: u_freeentry() (line 1847)
Adaptation: vim_free() -> xfree() (semantic equivalent)
Status: Patch generated and validated
Example 3: Batch scan against multiple CVEs
User: "Scan our embedded TLS library against CVE-2024-001 through
CVE-2024-005 from OpenSSL advisories."
Approach:
1. For each CVE, build a VKB entry: retrieve the OpenSSL patch,
extract the vulnerable function, root cause, and analysis points.
2. For each CVE, run detection against the target TLS library source.
3. For matches found, port analysis points accounting for the target
library's different API naming (e.g., `ssl_read` vs `tls_read`).
4. Confirm each candidate. Mark false positives where the target
library's implementation diverges sufficiently.
5. Generate patches for confirmed vulnerabilities.
6. Validate all patches.
7. Produce a summary table:
Output:
| CVE | Function | Status | Patch |
|----------------|------------------|-----------------|-------|
| CVE-2024-001 | tls_handshake() | CONFIRMED+FIXED | Yes |
| CVE-2024-002 | - | NOT FOUND | N/A |
| CVE-2024-003 | tls_decrypt() | FALSE POSITIVE | N/A |
| CVE-2024-004 | cert_verify() | CONFIRMED+FIXED | Yes |
| CVE-2024-005 | tls_handshake() | CONFIRMED+FIXED | Yes |
3/5 CVEs confirmed and patched. 1 not present. 1 false positive
(target uses constant-time comparison, neutralizing the timing
side-channel).
Best Practices
- Do: Always build explicit analysis points before confirming a vulnerability. Vague "this looks vulnerable" reasoning produces false positives. Each analysis point should be a specific, testable logical condition.
- Do: Retrieve cross-function and cross-module context during confirmation. A function that appears vulnerable in isolation may be protected by caller-side validation or type constraints visible only at the repository level.
- Do: Run both syntactic clone detection and semantic similarity matching during detection, then take the union. Neither method alone catches all recurring instances.
- Do: Perform consistency checks before generating patches. A patch that references functions or types absent from the target repository will not compile.
- Avoid: Skipping the confirmation stage. Detection alone produces high false-positive rates (the paper found 21 false positives out of 89 detections without confirmation). Confirmation improves repair accuracy by ~39.5%.
- Avoid: Assuming identical function names mean identical semantics across repositories. Forks diverge — always verify that the execution context and data flow match the original vulnerability's trigger chain.
- Avoid: Generating patches purely from the CVE description without examining the original patch. The historical patch encodes the maintainer's intended fix strategy and is the strongest signal for correct repair.
Error Handling
- No syntactic match found but vulnerability suspected: Fall back to semantic search — look for functions performing the same operation (e.g., "parses X.509 certificates") even if the code has been substantially rewritten. Use call graph analysis and string literal matching.
- Analysis points cannot be ported (missing structures/APIs): The target codebase may have diverged too far. Document which analysis points could not be mapped and flag the finding as "inconclusive — manual review required."
- Generated patch fails validation: Do not iterate more than once automatically. Report the failure with the validation agent's analysis of why the patch is insufficient, and present both the attempted patch and the remaining vulnerability conditions to the user for manual resolution.
- Multiple candidate functions match: Process each independently. Different clones of the same vulnerable function may have diverged differently — some may be vulnerable while others are not.
- CVE lacks a public patch commit: Build analysis points from the CVE description and CWE category alone. Detection and confirmation can still proceed, but repair accuracy will be lower without a reference patch. Flag this limitation in the report.
Limitations
- This approach is most effective for recurring vulnerabilities — flaws that exist because code was copied, forked, or reused. Novel, first-occurrence vulnerabilities without historical analogues cannot be detected this way.
- Detection relies on meaningful code similarity between the known vulnerable function and the target. If the target has been heavily refactored (e.g., rewritten in a different language or with completely different control flow), clone-based detection will miss it.
- Patch generation quality depends on the structural similarity between the original and target repositories. High divergence (renamed types, reorganized modules, different memory management models) reduces repair accuracy.
- The confirmation stage can produce false negatives if the context-retrieval does not surface a critical dependency (e.g., a macro defined in a deeply nested header that changes the function's behavior).
- Validation through re-detection is not equivalent to full formal verification. The patch may be semantically correct but syntactically different enough to still trigger the detector (false alarm) or may fix the detected pattern while leaving a subtler variant.
- LLM-based analysis points and confirmation reasoning can hallucinate — always treat outputs as recommendations requiring human review before merging patches into production code.
Reference
Paper: Zheng, Z., Zhou, J., Hu, X., Gao, Y., & Pan, S. (2026). Multi-Agent End-to-End Vulnerability Management for Mitigating Recurring Vulnerabilities. arXiv:2601.17762v1. https://arxiv.org/abs/2601.17762v1
Key takeaway: The five-stage pipeline (knowledge base, detection, confirmation, repair, validation) with ported analysis points and repository-level context retrieval achieves 57.3% end-to-end repair accuracy on real-world patch-porting cases, outperforming baselines by 31.9%-45.2%. The confirmation stage alone accounts for a 39.5% accuracy improvement.