Background
CVE-2026-50219 was a class of vulnerabilities in libexpat where five functions could be called from within active XML handlers, leading to heap use-after-free conditions. The fix, merged via PR #1246, introduced an isCalledFromInsideHandler() guard on all five functions: XML_GetBuffer, XML_Parse, XML_ParseBuffer, XML_ParserFree, and XML_ParserReset. The security community accepted the fix. The CVE was closed. Vorthix disagreed.
How the AI Found It
Phase 1 — Understanding the fix's assumption
The agent read PR #1246 and identified exactly what the fix assumed: that m_handlerCallDepth would be incremented by beforeHandler() and decremented by afterHandler() around every handler invocation. The guard isCalledFromInsideHandler() reads this counter and returns true only when it is greater than zero. If the counter stays at zero during a handler call, the guard silently returns false — and all five protected functions are bypassed.
Phase 2 — Finding every call site
Rather than reading only the fixed code path, the agent mapped every call site that could invoke m_characterDataHandler in xmlparse.c. In doContent(), the normal text processing path, the handler is invoked correctly with beforeHandler() / afterHandler() wrapping. In doCdataSection(), the XML_TOK_DATA_CHARS case invoked the same handler with no beforeHandler(). No afterHandler(). The depth counter stays at zero. The guard returns false while a handler is actively executing inside a CDATA section.
Phase 3 — Dynamic confirmation
A minimal proof of concept was constructed: a parser, a character data handler that calls XML_ParserFree on the global parser instance, and a single CDATA XML input. Under seventeen lines of C. Compiled with AddressSanitizer and run against the patched library (commit 429059e, the latest upstream master including the full merged PR #1246 fix).