Authored by Md Shoaib Shahriar Ibrahim and Saadman Ahmed, security engineers at OpenRefactory. Edited by Charlie Bedard
Overview
In today’s fast-paced world of software development, security vulnerabilities are an ever-present risk. While patching a vulnerability addresses the immediate problem, understanding the root cause is critical to prevent future issues, improve code quality, and strengthen overall security.
But here’s the catch: finding the root cause of a vulnerability is time-consuming, complex, and often requires deep expertise. That’s why we built an AI-powered agent that automates this process by taking a CVE ID as input and outputting the method(s) or function(s) responsible for the vulnerability.
In this blog, we introduce our CVE Root Cause Identification Agent, discuss its relevance, and outline how it functions. Through a pair of case studies, we explore the agent’s practical applications. These case studies illustrate both the strengths and limitations of current language model-based approaches.
One case study, in particular, reveals an interesting divergence in reasoning between different large language models, highlighting how variations in model interpretation can lead to differing conclusions—even when analyzing the same input. This observation underscores the complexity of automated vulnerability analysis and the importance of model reliability.
Root Cause Identification Challenge
One of the biggest hurdles in identifying the root cause of a CVE is locating the exact commit(s) where the vulnerability was introduced or patched. While the NVD (National Vulnerability Database) provides a description and severity details of a CVE, it often doesn’t include a direct link to the specific code commit where the vulnerability was fixed or first introduced. Security teams are frequently left to hunt through repositories, mailing lists, issue trackers, and security advisories to find the relevant commit. This manual process is time-consuming, inconsistent, and prone to human error.
Even after locating the commit, the challenge doesn’t stop there. Not every code change in a commit is necessarily related to the root cause. Commits can include:
- Patch code that fixes the vulnerability but doesn’t reveal what initially caused it
- Refactoring or unrelated changes bundled in the same commit
- Large diffs that obscure the critical parts of the fix
Understanding the context of the code change, which function or method actually caused the vulnerability versus which part of the code fixed it, requires deep domain expertise and manual review of the codebase.
Additionally, vulnerabilities often involve complex data flows.
To better understand the workflow, we first define Entry Point Function, Propagation Function and Sink:
- A vulnerability might be introduced in an entry point function, but only lead to exploitation due to propagation through multiple layers of code.
- Identifying whether a function is an entry point, a propagation function, or a sink where the vulnerability manifests is a nuanced task that requires tracing the flow of untrusted data, analyzing sanitization gaps, and understanding execution contexts.
Finally, software repositories are massive, spanning hundreds or thousands of files and functions. Finding the one or few functions that are directly responsible for a vulnerability is like finding a needle in a haystack—especially when the haystack keeps growing.
Our Solution: The CVE Root Cause Identification Agent
We developed an AI agent that takes a CVE ID and automatically analyzes the related code changes (commits) to pinpoint the function(s) or method(s) responsible for the vulnerability.
Key Features:
-
- Input: CVE ID
Accepts a CVE identifier as input to initiate the analysis. - Output: Root cause function(s)/method(s), their roles, and associated packages
Identifies and classifies functions or methods involved in the vulnerability as entry point, propagation, or sink, along with the package they belong to. - Commit Pathway Identification:
Automatically traces and identifies the most relevant commit URL where the root cause is located, even in cases where the path to the commit is non-linear or indirect. - JSON Output:
Delivers structured results in JSON format, enabling seamless integration into security dashboards, vulnerability tracking systems, or automated workflows. - Root Cause Focus (Not Patch Details):
Emphasizes identifying what caused the vulnerability, rather than what fixed it—helping teams better understand the origin of security issues.
- Input: CVE ID
Presenting 2 Case Studies
The following presents case studies that demonstrate the use of the agent. We discuss two specific cases. The first case study focuses on CVE-2022-36056, a vulnerability in Sigstore’s Cosign. For this, we conducted experiments primarily using Anthropic Claude and Gemini, and observed that both models produced similar results.
However, in the second case study involving CVE-2019-11253—the YAML “Billion Laughs” vulnerability in Kubernetes—we found a significant discrepancy between the outputs of the two models. To ensure the reliability of our findings, we executed both models twice and further analyzed the consistency of their outputs. These aspects are discussed in greater detail below.
Case Study 1: CCVE-2022-36056 in Sigstore’s Cosign
Background
CVE-2022-36056 was a vulnerability discovered in Sigstore’s Cosign, a tool used for signing and verifying container images. The vulnerability allowed an attacker to potentially bypass signature verification in certain scenarios.
Challenge-
- The NVD entry provided a general description of the issue but didn’t provide any links to the exact commit or source code that caused the vulnerability.
- Our security team had to manually trace discussions, GitHub issues, and PRs to locate the relevant commit.
- Once the commit was identified, we found multiple file changes and diff lines, including both the fix and unrelated code refactoring.
What Our Agent Did
-
- The agent goes through every hyperlinks provided by the NVD and extracts the URL of the github commit that actually introduced the vulnerable method causing the CVE.
- Then the agent analyzed the changes across critical files which are changed by that commit and identified the verifyBlob function in cmd/cosign/cli/verify/verify_blob.go as the entry point where improper validation was happening.
- It classified the role of verifyBlob as the entry point for the vulnerability and excluded unrelated functions that appeared only in the patch.
Outcome
-
- The agent’s identification matched manual security reviews. The agent took only a couple of minutes to identify the methods causing the vulnerability.
- It produced a JSON output that could easily be integrated into vulnerability management workflows.
Case Study 2: CVE-2019-11253 – YAML “Billion Laughs” Vulnerability in Kubernetes
Background
CVE-2019-11253, also known as the “Billion Laughs” vulnerability, impacted Kubernetes through its use of the gopkg.in/yaml.v2 library. The vulnerability allowed attackers to send malicious YAML or JSON payloads that caused excessive CPU and memory consumption, leading to denial-of-service (DoS) conditions in the Kubernetes API server. This type of attack exploits how YAML parsers handle complex, nested structures without limits, leading to resource exhaustion.
Challenge
When we set out to identify the root cause of CVE-2019-11253, we quickly realized how difficult it was to find a precise and consistent answer, even among advanced language models. The NVD description was generic and didn’t pinpoint any specific file, function, or commit that introduced or fixed the vulnerability.
Even after locating the related commit, there were multiple files, refactoring, and function changes, which made it challenging to isolate the core vulnerability versus the patch implementation.
What Our Agent Did
Identifying the appropriate commit that contains the root cause is often challenging. While a direct commit link containing the root cause may occasionally be available, in most cases, locating the exact root cause is a complex and non-linear process.
This particular case exemplifies such difficulty, where the relevant commit could not be found through straightforward inspection. Our agent, capable of systematically identifying the appropriate commit by following a series of critical steps, aimed at isolating the root cause effectively. In this way,we automated the process of retrieving the exact commit diff from the upstream yaml.v2 repository.
Then, the agent systematically analyzed the code and consistently surfaced these functions as potential root causes:
-
- Unmarshal (sink)
- NewDecoder (entry point)
- marshal (sink)
- marshal (sink)
- resolve (sink)
- WithLimitDecodedValuesCount (sink)
Although the results produced by the agent mentioned in the previous section (What Our Agent Did) were manually verified by a security expert and considered accurate, initially we noticed some differences in the outputs produced by different models when using the agents. While this may seem a bit unexpected, this variation may be common in LLM models due to model hallucination or differences in reasoning patterns. It’s also quite interesting and points to how model behavior can vary—even when handling the same input. Further insights into these findings are presented in the following section.
Interesting Finding: Contradictions in Analysis
During our analysis of Case Study 2, we cross-verified the results using multiple Large Language Models (LLMs) to get a broader understanding of the root cause. A fascinating contradiction arose between the analysis results from Anthropic Claude and Google Gemini in the file named: vendor/gopkg.in/yaml.v2/yaml.go,specifically regarding the function WithLimitDecodedValuesCount.
As LLM models are prone to hallucination, sometimes it misjudges and considers other functions as vulnerable although this occurs in most critical cases only where even human intervention also can be erroneous.
When both models were run initially, we got the following analysis results for the function name: WithLimitDecodedValuesCount.
Anthropic Claude’s Analysis:
Claude repeatedly flagged WithLimitDecodedValuesCount as the root cause, arguing:
“The absence of limits on decoded values was the root problem. The WithLimitDecodedValuesCount function was designed to impose such a limit but was removed in the patch diff. Without it, the YAML parser was left exposed to malicious payloads that could trigger resource exhaustion.“
Google Gemini’s Analysis:On the other hand, Google Gemini 2.0 Flash did not detect any vulnerability in that file at all. It simply stated:
“Did not get vulnerability in this file.“
Human Analysis:Based on manual validation by a security expert, Anthropic Claude’s analysis is correct in identifying WithLimitDecodedValuesCount as the root cause of the vulnerability. Its explanation aligns with the known behavior of the YAML “Billion Laughs” attack, which exploits the absence of decoding limits to cause resource exhaustion. In contrast, Google Gemini 2.0 Flash failed to detect any issue in the relevant file, missing a critical component of the vulnerability.
Further Contradictions in Analysis
Moreover, we observed additional contradictions between the models, particularly with regard to the exact functions and their roles in the vulnerability for the functions named Unmarshal and NewDecoder. Both models’ analytical views are discussed further.
Claude’s View:
Claude consistently flagged both Unmarshal and NewDecoder as key contributors to the vulnerability. We ran the Claude model several times to avoid any hallucinating output. It explained that:
-
- Unmarshal: This function is responsible for processing the YAML or JSON payloads, and without proper input validation, attackers can send malicious input that triggers excessive CPU and memory consumption.
- NewDecoder: As the entry point to the decoding process, it also lacked critical safeguards, making the entire process vulnerable to resource exhaustion.
This view was consistent across several runs of Claude, where it consistently tied both functions to the vulnerability, emphasizing the need for proper limits on decoded values to prevent such attacks.
Gemini’s View:
On the other hand, Google Gemini once again highlighted Unmarshal as the root cause but did not flag NewDecoder. Instead, it focused only on Unmarshal’s role in parsing the payloads without proper safeguards, which could lead to the DoS condition when processing malicious YAML or JSON.
This further contradiction between the two models illustrates the different levels of detail and analysis that each AI model provided. While Claude pointed out that both Unmarshal and NewDecoder should be fixed to ensure proper limits, Gemini focused primarily on the input parsing phase without identifying the full scope of the problem.
Human Analysis
From our security team’s analysis, this result made by Claude is appropriate in this case although Gemini was also close to the exact output.
Conclusion
While AI-driven tools, like our CVE Root Cause Identification Agent, offer significant advancements in automating vulnerability analysis and root cause identification, it’s important to acknowledge that AI still has limitations. As demonstrated in the analysis of the two case studies, even sophisticated models can produce conflicting interpretations depending upon how they weigh code context, logic, and protective mechanisms. Occasional misjudgments, whether from AI or human reviewers, highlight the inherent challenges in complex security analysis.
In the future, expanding this system could dramatically improve the speed, consistency, and depth of security assessments helping organizations not only patch vulnerabilities but truly understand and prevent them from recurring. The combination of AI-driven automation and continuous improvement offers a promising path forward in strengthening software security at scale.