CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-24515

libexpat's Pointer Amnesia: A Tale of Missing User Data (CVE-2026-24515)

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 4, 2026·6 min read·83 visits

Executive Summary (TL;DR)

libexpat versions < 2.7.4 forget to copy the `userData` pointer when creating a subparser for external entities with unknown encodings. If an application uses a custom encoding handler and accesses that data, it crashes (NULL dereference).

A deep dive into a logic flaw within libexpat's external entity parsing mechanism. Specifically, the library fails to inherit user-context data when creating child parsers for unknown encodings, leading to NULL pointer dereferences in applications that rely on custom encoding handlers. While the CVSS score is low due to high complexity, the bug reveals a fundamental oversight in state management within one of the world's most ubiquitous C libraries.

The Hook: XML, The Gift That Keeps on Giving

If you've been in this industry longer than five minutes, you know that XML parsers are the gift that keeps on giving. From XXE (XML External Entity) attacks that read your /etc/passwd to Billion Laughs attacks that eat your RAM for breakfast, XML has been keeping security researchers employed for decades. Today, we're looking at libexpat, the granddaddy of stream-oriented XML parsers. It's written in C, it's fast, and it is embedded in absolutely everything—from Python's xml.parsers.expat to your browser, and likely the firmware of that smart fridge judging you for eating cheese at 3 AM.

But here's the thing about C libraries: they rely heavily on context pointers (void *userData) to maintain state. Since C isn't object-oriented in the traditional sense, if you want a callback function to know which connection or request it's handling, you have to manually pass a pointer to that state every single time. It's a game of hot potato.

CVE-2026-24515 is what happens when someone drops the potato. It's a NULL Pointer Dereference (CWE-476), which sounds boring until you realize it happens during the complex dance of handling external entities combined with unknown encodings. It's a corner case of a corner case, but it exposes a sloppy logic error in how parsers spawn child parsers. The developers implemented the cloning of the handler function perfectly but completely ghosted the data meant to go with it.

The Flaw: Inheritance is Hard

Let's talk about "Parser Inheritance." In libexpat, when the main parser encounters an external entity (like <!ENTITY x SYSTEM "foo.xml">), it doesn't just read that file inline. It creates a brand new parser instance—a subparser—to handle that external context. This subparser is supposed to be a clone of the parent in terms of configuration. It inherits the handlers, the settings, and crucially, the User Data.

Imagine you are a parser. You have a custom handler for weird character encodings (let's say, EBCDIC or some cursed proprietary format). You also have a pointer to a struct containing your application state (0xCAFEBABE). When you spawn a child parser to handle an external file, you tell the child: "Hey, if you see a weird encoding, use this function." Vulnerable versions of libexpat did exactly that.

However, they forgot the second part of the sentence: "...and here is the state pointer (0xCAFEBABE) you need to do your job." instead, the child parser initializes with the correct function pointer but a NULL data pointer. When the child parser hits an unknown encoding in the external entity, it calls the function. The function expects a valid pointer, tries to read from address 0x0, and the OS kernel steps in to smack the process with a SIGSEGV.

It's like hiring a contractor to paint a house, giving them the address, but forgetting to give them the keys. They show up (the handler is called), try to open the door (dereference the pointer), and hit a wall.

The Code: The One-Line Omission

The vulnerability lives in expat/lib/xmlparse.c, specifically in the function XML_ExternalEntityParserCreate. This function is responsible for birthing the subparser. Let's look at the diff. It is painfully simple, as most devastating C bugs are.

In the vulnerable code, the library diligently copies the m_unknownEncodingHandler function pointer. But notice what is missing immediately after.

// expat/lib/xmlparse.c - XML_ExternalEntityParserCreate
 
// ... setup code ...
 
/* The logic copies the handler function... */
parser->m_unknownEncodingHandler = oldParser->m_unknownEncodingHandler;
 
/* ... but where is the data? */
/* The variable m_unknownEncodingHandlerData is ignored! */
 
// ... rest of initialization ...

The fix, introduced in version 2.7.4, is literally one assignment. This is the difference between a stable application and a denial-of-service vector:

// THE FIX
parser->m_unknownEncodingHandler = oldParser->m_unknownEncodingHandler;
// Added in 2.7.4:
parser->m_unknownEncodingHandlerData = 
    oldParser->m_unknownEncodingHandlerData;

Without this line, parser->m_unknownEncodingHandlerData defaults to NULL (via memset or initialization). The irony here is that libexpat is usually very careful about state. This specific struct member just slipped through the cracks during the cloning process, likely because UnknownEncodingHandler is a rarely customized feature compared to StartElementHandler or CharacterDataHandler.

The Exploit: Crashing the Party

To exploit this, we don't need memory corruption magic or heap spraying. We just need to force the application down a code path where it relies on that missing pointer. The prerequisites are high (CVSS AC:H), but for an attacker targeting a specific appliance or custom server, it's viable.

The Recipe for Disaster:

  1. Target: Find an app that uses libexpat and calls XML_SetUnknownEncodingHandler passing a non-NULL userData pointer.
  2. Vector: The app must parse XML with external entities enabled (default in many older configs, though often disabled now for security).
  3. Trigger: The external entity must declare an encoding that the parser doesn't recognize natively (e.g., encoding='x-user-defined').

Here is the attack flow:

The PoC XML looks innocuous. The main file:

<!DOCTYPE root [
  <!ENTITY payload SYSTEM "payload.ent">
]>
<root>&payload;</root>

And the referenced payload.ent file which triggers the encoding handler:

<?xml version='1.0' encoding='x-oops'?>
<data>Boom</data>

When the parser reads payload.ent, it sees x-oops. It doesn't know what that is. It looks up the handler. It calls the handler. The handler tries to log "Encountered encoding x-oops for user [Pointer]"... and the process dies.

The Impact & Mitigation: Why Panic?

Is this the next Heartbleed? No. It's a NULL dereference, not a buffer overflow or logic bypass allowing RCE. The primary impact is Denial of Service (DoS). However, do not underestimate the annoyance of a crash. If this parser is part of a critical daemon processing XML feeds (like an RSS aggregator, a SOAP backend, or a configuration loader), a single malformed request can take down the service.

The Fix: Upgrade to libexpat 2.7.4. It was released specifically to address this. If you are a developer using libexpat directly, there is also a defensive coding lesson here: Never trust your pointers.

Even if you know you passed a pointer in setup, your callback should look like this:

int my_encoding_handler(void *encodingHandlerData, ...) {
    if (!encodingHandlerData) {
        // The parser betrayed us.
        return XML_STATUS_ERROR;
    }
    // Safe to proceed
}

This defensive check would neutralize the vulnerability even on the older library version. Trust no one, not even your own libraries.

Official Patches

libexpatOfficial fix and regression test

Fix Analysis (1)

Technical Appendix

CVSS Score
2.9/ 10
CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
EPSS Probability
0.01%
Top 98% most exploited

Affected Systems

libexpat < 2.7.4Systems processing untrusted XML with external entities enabledApplications using XML_SetUnknownEncodingHandler

Affected Versions Detail

Product
Affected Versions
Fixed Version
libexpat
libexpat
< 2.7.42.7.4
AttributeDetail
CWE IDCWE-476 (NULL Pointer Dereference)
Attack VectorLocal / Context-dependent (Requires specific app config)
CVSS v3.12.9 (Low)
ImpactDenial of Service (Application Crash)
EPSS Score0.00013 (Low probability of wild exploitation)
LikelihoodLow (Requires custom handler + external entities)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1499Endpoint Denial of Service
Impact
CWE-476
NULL Pointer Dereference

A NULL pointer dereference occurs when the application dereferences a pointer that it expects to be valid, but is NULL, typically causing a crash or exit.

Known Exploits & Detection

libexpat PR #1131Unit test (test_unknown_encoding_user_data_secondary) demonstrating the crash.

Vulnerability Timeline

Patch authored by Sebastian Pipping
2026-01-18
CVE-2026-24515 Published
2026-01-23
libexpat 2.7.4 Released
2026-01-23

References & Sources

  • [1]Fix PR on GitHub
  • [2]NIST NVD Entry
  • [3]CWE-476: NULL Pointer Dereference

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•2 days ago•GHSA-7PPR-R889-MCF2
7.5

GHSA-7PPR-R889-MCF2: Unbounded WebSocket Message Aggregation in http4s-blaze-server leads to Denial of Service

An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.

Alon Barad
Alon Barad
7 views•5 min read
•2 days ago•GHSA-95CV-R8X4-VH75
7.6

GHSA-95cv-r8x4-vh75: Path Traversal Vulnerability in OpenList Batch Rename Handler

A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.

Amit Schendel
Amit Schendel
9 views•7 min read
•2 days ago•GHSA-P6PH-3JX2-3337
4.3

GHSA-P6PH-3JX2-3337: Horizontal Privilege Escalation and Metadata Information Disclosure via Bleve Search in OpenList

OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•GHSA-86CX-WWF4-PHQ4
6.5

GHSA-86cx-wwf4-phq4: Path Prefix Confusion Authorization Bypass in OpenList

An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.

Amit Schendel
Amit Schendel
7 views•6 min read
•2 days ago•CVE-2026-16584
7.0

CVE-2026-16584: Security Policy Bypass in AWS API MCP Server via Startup Initialization Failure

A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.

Amit Schendel
Amit Schendel
12 views•7 min read
•2 days ago•GHSA-6V4M-FW66-8R4X
6.5

GHSA-6V4M-FW66-8R4X: Path Disclosure and Shell Expansion Bypass in Shescape

An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.

Alon Barad
Alon Barad
6 views•7 min read