Multi-patch vulnerability fixes can leave open source exposed

Vulnerability management runs on a shorthand. A CVE shows a linked patch, someone applies it, and the ticket moves to closed. That shorthand covers most open source fixes. A share work in a different way, arriving as a run of two or more commits where the first one leaves the flaw in place.

multi patch vulnerability fixes

Researchers at the University of Texas at Dallas went through 1,646 open source CVEs that carry more than one patch in the National Vulnerability Database, drawn from records filed between 1999 and 2025. Those cases are a small share of the whole, close to one in fifteen of the open source CVEs in the database that carry a linked patch. The operational weight sits in the interval between the first patch and the last one, a window in which the software stays open.

The group averaged 2.55 patches per CVE, and the load falls unevenly across projects. ImageMagick, which keeps several release lines alive at once, needed more than one commit for close to a third of its fixes, a rate driven by porting the same repair to every supported version.

Three ways a single fix comes up short

The team sorted the multi-patch cases into three groups. The largest covers vulnerabilities that live in more than one place. Similar buggy code shows up across separate branches, methods, or projects, and Git cannot apply one commit to every branch at once, so a vendor ports the change to each affected location. Fixes spread across different branches or projects made up the single biggest subcategory, at 830 records.

A second group bundles the security change with related work, such as a temporary workaround, a changelog entry, or a documentation update committed on its own. The third group carries the most risk. These are defective fixes, where the first patch either misses part of the vulnerability or adds a new bug. Incomplete fixes alone accounted for 641 of the records, the second largest subcategory in the set.

An integer overflow in the Linux XFS file system, tracked as CVE-2012-0038, shows the pattern. The first commit added a bounds check. It relied on a helper that returns an unsigned integer, feeding a value the code treated as signed, so the check could be bypassed. A second commit changed the variable type and closed the hole. The complete fix landed 18 days after the first attempt.

Detection tools miss the leftover risk

Automated tooling offers little help in telling a partial fix from a complete one. The researchers ran seven detection models across the incomplete-fix set, including CodeBERT, UniXcoder, LineVul, Devign, and ReVeal, and asked each to label patched code as vulnerable or clean.

Accuracy and F1 for every model landed below 50%, a floor the authors call worse than random guessing. The models tend to give the pre-fix, intermediate, and post-fix versions of a function the same label, because a security patch changes a small slice of code.

The graded models were open source research systems tested on public data. Weiliang Qi, a co-author of the study, said the team left commercial products out of the test on purpose. “Because our test cases come from public vulnerability records, proprietary tools may already contain signatures for the same CVEs, making it difficult to distinguish genuine generalization from prior knowledge,” Qi told Help Net Security. His expectation for how those products would perform rests on how they work: “most commercial tools, to the best of our knowledge, rely on techniques such as signature matching and code patterns, which are similar to the approaches underlying the tools in our evaluation. We therefore expect them to face similar limitations in detecting unseen incomplete and multi-location fixes.”

Tools that hunt for copies of vulnerable code across a codebase struggled in the same setting. Two open source clone detectors, ReDebug and FIRE, were pointed at the multi-location cases, using the first patch to build a signature for later sites. FIRE’s ability to catch the recurring vulnerable code fell from 90 to about 52 on its true positive rate. Vulnerable sites in these cases differ enough from one another that a signature built from the first location misses the rest.

The window between patches

Timing turns these gaps into exposure. Close to a third of multi-patch fixes, 31.7%, take more than a day to move from the first commit to the last. Cross-branch and cross-project ports run the longest, and the delay creates a race. Once one branch carries a public fix, attackers can read the same repository, spot the equivalent weakness in an unpatched branch, and work it before the port arrives.

An arbitrary file upload flaw in Chamilo LMS, tracked as CVE-2023-4226, ran this way. A workaround shipped first, and the formal fix followed 16 days later.

Qi was careful about what the data supports. “We do not find direct evidence of exploitation during these intervals, and our study measures the exposure window rather than attacker activity, so the risk we describe is structural at this point,” he said. He pointed to code reuse across projects as a related signal that the security community already treats as serious. “We believe the risk is real, and one indirect example is that vulnerabilities arising from code reuse across different projects have already drawn community attention, leading to a series of detection tools such as VUDDY, MOVERY, and FIRE,” Qi said. “Multi-patch cases represent a similar pattern within a single project, where an early patch in one location can reveal clues about similar flaws in unpatched locations, and we believe they carry a comparable risk of exploitation.”

Patch records add their own noise

Patch records themselves add friction. About 5.8% of the multi-patch cases include commits with no security role, such as README edits, version bumps, and test files, which raise the cost of automated analysis built on the data.

One record, tracked as CVE-2022-2522, kept a commit that was the parent of the security fix after a user pointed out the error and the vendor declined to correct it. Vulnerability datasets built by reversing patches inherit this noise, and reversing a later commit can produce an in-between state that carries traits of both the vulnerable and the repaired code.

Treating a linked patch as the end of a vulnerability’s life works for the common case. The sequence fixes call for an extra step. A high-severity CVE with a single linked commit deserves a check for follow-up patches and a look at which branch the fix belongs to before it goes live. The label on an NVD entry marks the start of remediation for a substantial slice of open source flaws, and the code carries the rest.

Don't miss