Vulnerability Response

CVE-2025-49794 in libxml2: Patch Posture & SBOM Response

libxml2 use-after-free during XPath schematron parsing scored CVSS 9.1. Defender SBOM playbook for one of the most-embedded libraries on the planet.

Yukti Singhal
Security Researcher
6 min read

On July 8, 2025, the libxml2 maintainers published a security release addressing CVE-2025-49794, a use-after-free vulnerability in the XPath element handling code when XML schematron documents contain <sch:name path=.../> elements. Red Hat assigned CVSS v3.1 base score 9.1 (vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H). The same release also fixed the closely related CVE-2025-49796 (CVSS 9.1, similar root cause in a different XPath code path). libxml2 is among the most widely embedded libraries in the world — shipping inside Apple platforms, Android, every Linux distro, PHP, Python (via lxml), Ruby (via Nokogiri), Java (via JAXP backends in some JDKs), every browser engine, and thousands of network appliances. The SBOM detection challenge is the headline story.

What does the vendor advisory say?

The libxml2 maintainers' advisory describes CVE-2025-49794 as a use-after-free in xmlSchematronCompile, the function responsible for parsing schematron XML documents with embedded XPath expressions. When the schematron contains a <sch:name path=.../> element with specific malformed payloads, the XPath evaluator frees a node and then attempts to dereference it, leading to memory corruption. Successful exploitation produces a program crash; under platform-specific conditions, the use-after-free can be steered into arbitrary code execution, though the maintainers do not characterize this outcome as reliable. The fix re-orders the deallocation sequence in xmlSchematronCompile and adds null-pointer guards in the XPath evaluator. The advisory explicitly calls out that the bug is reachable only when an application processes schematron XML — which sounds narrow but in practice covers a long list of document-validation pipelines, healthcare interchange (HL7), publishing, and government records management.

Which versions are affected and which are patched?

CVE-2025-49794 affects libxml2 from version 2.0.0 through 2.12.10 and 2.13.0 through 2.13.7. Fixed releases:

  • libxml2 2.12.11 (long-term maintenance branch)
  • libxml2 2.13.8 (current stable branch)
  • libxml2 2.14.2 (development branch, which also fixed CVE-2025-32414 — a related Python-bindings issue)

Downstream distribution patched builds:

  • Red Hat Enterprise Linux 9: libxml2-2.9.13-9.el9_5.1 (RHSA-2025:12450)
  • Red Hat Enterprise Linux 8: libxml2-2.9.7-19.el8_10.1 (RHSA-2025:12451)
  • Debian 12: libxml2 2.9.14+dfsg-1.3+deb12u3
  • Debian 13: libxml2 2.12.7+dfsg-3+deb13u1
  • Ubuntu 24.04 LTS: libxml2 2.9.14+dfsg-1.3ubuntu3.2
  • Alpine Linux 3.19+: libxml2 2.12.11-r0
  • AWS Linux 2023: libxml2 2.10.4-3.amzn2023.0.5
  • Apple macOS 15.6 and iOS 18.6 (per Apple's August 2025 security release notes)
  • Android: AOSP patchlevel 2025-08-05

Language bindings:

  • Python lxml — versions before 5.3.1 carry vulnerable libxml2 when statically built; lxml 5.3.1 ships fixed libxml2 in its wheel builds.
  • Ruby Nokogiri — versions before 1.18.4 vulnerable in static-build mode; 1.18.4 rebuilt with libxml2 2.13.8.
  • PHP — patched via the distribution's PHP package, which dynamically links libxml2.

Is it in CISA KEV and what is the EPSS score?

CVE-2025-49794 is not in CISA KEV. EPSS at publication was 0.03, climbing to 0.09 over 30 days. The exposure is structural rather than acutely active: libxml2 bugs of this class are weaponized through document-handling pipelines that take months for attackers to map, and the long tail of vulnerable copies persists for years inside embedded firmware. The right framing for defenders is the same as for OpenSSL — even when KEV does not list it, patch as part of routine quarterly inventory drives because the next exploit campaign will pull from these CVEs and the SBOM cleanup is what determines blast radius.

How do you find vulnerable instances in your SBOM?

libxml2 is the canonical SBOM-driven CVE because it lives at the bottom of so many dependency stacks. Safeguard saved query:

# Identify every artifact containing libxml2 in the affected range
safeguard scan --cve CVE-2025-49794 --cve CVE-2025-49796 \
  --component "pkg:generic/libxml2"

# Surface language wrappers that statically embed libxml2
safeguard sboms query \
  --component "pkg:pypi/lxml@<5.3.1" \
  --component "pkg:gem/nokogiri@<1.18.4" \
  --component "pkg:npm/xmldom@<0.8.10"

For shops on Syft + Grype, the equivalent invocation is grype dir:./ --only-fixed --by-cve CVE-2025-49794. For containerized estates, scan the entire image catalog (grype registry:my-registry/...) and prioritize images with internet-facing services that parse user-supplied XML. The most-often-forgotten copies are: network appliance firmware (Cisco, Fortinet, F5, NetScaler), iOS/Android in-app document viewers, and PDF/EPUB reader applications that process embedded XML metadata.

What is the recommended patch rollout?

libxml2 patches are normally distributed via the OS package manager, so the rollout follows the distro's standard cadence:

  1. Pull the patched package from the upstream distro repository.
  2. Rebuild and republish every container base image consuming that distro.
  3. Trigger downstream rebuilds across CI for every service consuming the base image.
  4. Roll out via blue/green or rolling update; verify with xmllint --version in each pod.
  5. For language wrappers (lxml, Nokogiri), bump the gem/pip dependency in the application's manifest and republish.
  6. For embedded firmware (network appliances, IoT), wait for the vendor advisory and apply the firmware update through normal change management.

Compensating control while patching: disable schematron processing in applications that do not need it. lxml exposes this through etree.XMLParser(no_network=True, resolve_entities=False) configuration; Nokogiri through Nokogiri::XML(input) { |c| c.nonet.noent }; PHP through libxml_disable_entity_loader(true) (deprecated since PHP 8.0 because the default changed, but still worth verifying). Disabling schematron in code does not patch the library but eliminates the reachable trigger.

What detections does the vendor or CISA publish?

There is no network signature for CVE-2025-49794 because XML parsing happens inside the application server after the document has crossed any WAF. Defenders should monitor application crash signals and use distro-provided compliance content. Red Hat publishes an OpenSCAP content stream that defenders can run as part of compliance scanning:

# Source: Red Hat OpenSCAP content for RHSA-2025:12450
oscap oval eval --results /tmp/cve-2025-49794.xml \
  --report /tmp/cve-2025-49794.html \
  /usr/share/xml/scap/ssg/content/com.redhat.rhsa-RHEL9.oval.xml

# Quick distro-agnostic version check
xmllint --version 2>&1 | head -2
ldd $(which xmllint) | grep libxml2

For Kubernetes estates, Trivy's compliance-mode scan (trivy fs --compliance docker-cis-1.6.0) will surface vulnerable libxml2 inside running pods.

For Kubernetes pods, the verification flow combines kubectl exec and the package query: kubectl exec -n <ns> <pod> -- sh -c 'xmllint --version 2>&1 | head -2'. For Apple ecosystems, Xcode 16.6 and the Apple security release notes (HT215543) document the affected libxml2.dylib build identifier; iOS device management tools (Jamf, Kandji) can enforce minimum OS versions to ensure mobile devices are running the patched library. The long-tail SBOM problem with libxml2 is statically linked copies inside Go binaries built with cgo against system libxml2 — the only reliable detection is to scan the binary's .rodata section for the version string, which Trivy and Syft both attempt automatically.

How Safeguard Helps

Safeguard's SBOM matcher resolves libxml2's purl identifier across every packaging ecosystem and language wrapper, so a single CVE-2025-49794 query finds the bug whether it ships as a Debian package, an Alpine apk, a vendored copy inside an iOS app's .ipa, or a statically linked symbol inside a Go binary that wraps libxml2-sys. Policy gates fail CI builds promoting any artifact still matching the CVE, and VEX statements from upstream maintainers and large vendors (Apple, Red Hat, Canonical) are auto-ingested for products whose configurations make the schematron path unreachable. Griffin AI scores affected services by external XML input — flagging public API endpoints that parse user-supplied XML above internal-only batch jobs. The remediation engine generates per-repository PRs that bump the language wrapper or base image, regenerate the lockfile, and re-run the build, closing the loop between SBOM detection and verified fix at the scale libxml2 demands.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.