CVE-2025-25341 Turns XML Into a Denial-of-Service Weapon

  • Name: libxmljs internal _ref access → segmentation fault
  • CVE: CVE-2025-25341.
  • CVSS v3.x (reported): 7.5 (High) — Network-accessible, no privileges required, availability impact.
  • Severity: High (denial-of-service / application crash).
  • Exploitability: Low complexity to trigger — an attacker only needs to send a crafted XML to a service that parses XML with the vulnerable libxmljs (≤ v1.0.11).
  • Exploit availability (public): No public weaponised wide-scale exploit campaigns reported at time of writing.

What the bug actually is

libxmljs is a Node.js binding to libxml2 used to parse and examine XML documents. In version 1.0.11 and earlier, when libxmljs parses an XML document that uses entities (for example <!ENTITY name "X"> and a reference &name;) the library exposes an internal property named _ref on nodes of type entity_ref and entity_decl. Reading that internal _ref property (for example via console.log(node['_ref']) or other accidental/deliberate access) causes the native binding to dereference memory incorrectly and leads to a segmentation fault — the Node.js process crashes immediately. That crash is effectively a denial-of-service for any application that uses the vulnerable library to parse untrusted XML.

Important nuance: the crash happens not only through library API calls — even inspecting the node object (or logging it) can trigger the crash because of how the native binding exposes _ref. That means the attack surface includes any code path (debugging, logging, admin endpoints, or normal parsing) that might touch node internals while parsing untrusted XML.


How it could be exploited (threat model / steps an attacker would take)

  1. Target: Any network-accessible service that accepts XML (SOAP endpoints, XML REST payloads, XML upload/parsing endpoints, integrations that parse XML attachments, etc.) and uses libxmljs ≤ 1.0.11.
  2. Craft an XML document containing an entity declaration and an entity reference. The XML can be simple — the PoC below shows the minimal payload.
  3. Send the XML to the vulnerable parsing endpoint. When the service parses the XML and either accesses or logs the node contents (or when the parser internal code touches _ref), the native binding dereferences invalid memory and the process crashes (segfault). This results in immediate DoS of the service.

Because there are no privileges or user interaction required and the payload is tiny, exploitation is straightforward wherever vulnerable parsing is exposed to attackers.


Exact PoC:

This is the PoC posted by the reporter on the libxmljs GitHub issue (keeps the original minimal structure):

// poc.js
libxmljs = require('libxmljs');

docText = `
<!DOCTYPE note [<!ENTITY writer "X">]>
<from>&writer;</from>
`;

doc = libxmljs.parseXml(docText);
from = doc.get('//from');
c = from.childNodes()[0];

// these lines demonstrate the crash
console.log(c.type());            // likely prints: entity_ref
console.log(Object.getOwnPropertyNames(c)); // likely prints: ['_ref']
console.log(c['_ref']);          // <-- this causes segmentation fault / crash

Running node poc.js against a vulnerable libxmljs will typically produce:

entity_ref
[ '_ref' ]
Segmentation fault (core dumped)

That demonstrates the minimal triggering payload and shows how trivial the XML needs to be.


MITRE / CWE mapping

  • Primary CWE: CWE-400 — Uncontrolled Resource Consumption (Denial of Service) — because the end result is service unavailability via crash.
  • Other mappings (contextual): this is a native memory safety issue in a language binding (Node ↔ native). From a CAPEC perspective, it’s a malformed input causing unexpected native behaviour pattern (feeding specially crafted XML). (Mapping derived from the technical details reported.)

Detection — how to know if you’ve been hit or are vulnerable

There are three main detection angles: (A) static detection (do you use the vulnerable version), (B) runtime detection (crash / logs), and (C) payload/traffic detection (network signatures).

A. Static checks

  • Inventory your Node projects / containers for libxmljs in package.json / package-lock.json / node_modules. If you see [email protected] (or older) you are vulnerable. Use npm ls libxmljs or scan images.

Example command:

# from your project root
npm ls libxmljs
# or search in a repository
grep -R "libxmljs" -n .

B. Runtime detection (what to look for in logs)

  • Segmentation fault / core dump: Node processes that crash with “Segmentation fault (core dumped)”, exit code 139, or OS kernel logs (dmesg / syslog) indicating segfault related to your Node process. Example log entries:
    • Segmentation fault (core dumped)
    • node[pid]: segfault at 0 ip ... in syslog/dmesg
    • Unexpected service restarts, supervised by systemd / PM2 / container restarts.
  • Application tracebacks: If the app logs show an immediate crash shortly after parsing XML input, correlate incoming XML requests with the time of crash.
  • Core dumps / coredumpctl: If you collect core dumps, the backtrace will point into the native binding (xmljs native module) exposing _ref.

Sample Splunk query to find candidate events (example):

index=app_logs OR index=syslog "Segmentation fault" OR "core dumped" 
| stats count by host, source, _time, process
| sort -_time

C. Network / payload detection (inspect incoming XML)

Because the PoC uses a DOCTYPE + ENTITY, you can detect requests that include <!DOCTYPE or <!ENTITY + an entity reference like &name;. Use WAF or IDS rules to flag such payloads.

Simple WAF/IDS indicators:

  • Presence of <!DOCTYPE or <!ENTITY in XML payloads posted to endpoints that shouldn’t receive DTDs.
  • Presence of &[a-zA-Z0-9]+; inside element content combined with DOCTYPE earlier in the same request.

Detection rules

1) Suricata / Snort

Detects HTTP requests containing <!DOCTYPE (basic; may need to be flow:established,to_server; etc.)

alert http any any -> any any (msg:"CVE-2025-25341 - XML DOCTYPE / ENTITY declaration detected"; \
content:"<!DOCTYPE"; nocase; http_client_body; depth:64; sid:1000001; rev:1;)

To tighten:

alert http any any -> any any (msg:"CVE-2025-25341 - XML ENTITY declaration + entity reference"; \
content:"<!ENTITY"; nocase; http_client_body; content:"&"; http_client_body; sid:1000002; rev:1;)

2) ModSecurity / WAF

Block or log requests with a DOCTYPE or ENTITY declaration in the body.

SecRule REQUEST_BODY "(?i)(<!DOCTYPE|<!ENTITY)" \
 "id:10001,phase:2,deny,log,msg:'Possible libxmljs entity DoS attempt - DOCTYPE/ENTITY present',t:none"

3) Sigma rule (SIEM alert) — generic

title: Possible libxmljs CVE-2025-25341 exploitation attempt
id: a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxx
status: experimental
description: Detects HTTP requests containing DOCTYPE or ENTITY declarations that may trigger libxmljs segmentation fault.
detection:
  selection:
    HttpRequestBody|contains:
      - "<!DOCTYPE"
      - "<!ENTITY"
  condition: selection
fields:
  - src_ip
  - dst_ip
  - url
level: high

4) Splunk example: find suspicious XML payloads

index=web_access sourcetype=access_combined
| where like(request_body, "%<!DOCTYPE%") OR like(request_body, "%<!ENTITY%")
| stats count by clientip, uri, _time
| sort -count

5) Elastic/Kibana KQL

http.request.body: "*<!DOCTYPE*" or http.request.body: "*<!ENTITY*"

What logs to monitor (log sources)

  • Application logs (Node stdout/stderr, application exception logs) — look for immediate crashes during XML parsing.
  • Container / container runtime logs (docker logs / kubectl logs) — restarts or segfault messages.
  • System logs (/var/log/syslog, dmesg) for “segfault” kernel messages.
  • WAF/Proxy logs (NGINX, Cloudflare, ModSecurity) for requests containing <!DOCTYPE or <!ENTITY.
  • Process supervisor logs (systemd, PM2) showing exits and automatic restarts.
  • Core dumps / crash reports — analyze native stack traces to confirm xmljs native module involvement.

Practical remediation & mitigations (what to do now)

  1. Immediate (if you’re using libxmljs ≤ 1.0.11):
    • Stop parsing untrusted XML with the vulnerable library. If an endpoint accepts arbitrary XML from untrusted sources, disable that functionality or place it behind strict filters.
    • WAF rule: deploy a ModSecurity rule to block or log requests containing <!DOCTYPE / <!ENTITY until you have a long-term fix. (See rules above.)
    • Harden process handling: run xml parsing in an isolated worker process (or container) so crashes affect only the worker and not the entire app. Use supervisors to detect worker crashes and implement rate-limiting or circuit breakers to avoid crash loops.
  2. Short/medium term:
    • Replace libxmljs with an actively maintained library (or call native libxml2 tools safely) if possible. The libxmljs project shows low maintenance activity and no released fix was available at the time of reporting; consider safer alternatives or maintained forks.
    • Sanitize input: reject requests with DOCTYPE/ENTITY if your app does not need DTDs or entities. Rejecting DTDs entirely is the simplest mitigation for many apps.
  3. Long term:
    • Patch/upgrade to a fixed version when an official patch is released. If no patch arrives (project abandoned), migrate to an alternative library (one that is actively maintained and uses libxml2 safely) or call external trusted XML processing (e.g., run xmllint in a sandbox) rather than linking an unmaintained binding.
    • Add tests/scan to detect use of unsafe XML parsing patterns in your codebase.

Official patch status

  • At the time this was published, no official security patch release for libxmljs addressing CVE-2025-25341 was available. The public, authoritative issue tracking the bug and PoC is the libxmljs GitHub issue where the reporter posted the PoC and discussion: GitHub issue #667 (libxmljs repository). This is the canonical project record for the vulnerability and currently the best “official” source.

Link (official project issue / canonical record):

  • GitHub issue describing the vulnerability and PoC: https://github.com/libxmljs/libxmljs/issues/667

If/when a patched release is published on the libxmljs releases page or on npm, that release page (or the npm package page) will be the official patch location. Right now the repository shows the latest release as v1.0.11 from 2023 and there is no tagged security fix release.


Indicators of Compromise (IoCs) & payload examples

Minimal malicious request body (the PoC XML; can be embedded in an HTTP POST body to a vulnerable endpoint):

<!DOCTYPE note [<!ENTITY writer "X">]>
<from>&writer;</from>

Search for this pattern in captured requests or logs to find attempted exploitation. Correlate timestamps of these requests with application crashes.


Detection caveats & false positives

  • Many legitimate XML documents can include DTDs and entities (though modern services often do not). Blocking every <!DOCTYPE everywhere can break legitimate traffic. Use risk-based placement of rules (e.g., block at external perimeter for endpoints that should not accept DTDs) rather than indiscriminate blocking everywhere.
  • Application debugging/logging that inspects node internals may trigger the crash even on otherwise harmless XML — be careful when instrumenting code in production.

Final practical checklist

  1. Inventory: run npm ls libxmljs across your codebase and container images. If found, mark them vulnerable.
  2. If vulnerable and exposed: block requests with <!DOCTYPE / <!ENTITY at the WAF and add detection rules (see ModSecurity / Suricata examples above).
  3. Run the PoC only in an isolated test environment to confirm vulnerability and crash behavior (do not run against production). The PoC is trivial — use it for confirmation.
  4. Plan migration to a maintained XML library or move parsing to an isolated service that can crash without taking the whole application down.
  5. Monitor logs (segfaults, core dumps, process restarts) and set SIEM alerts (the Splunk/Sigma examples above).

Final notes:-

  • This is a denial-of-service vulnerability that is easy to trigger where libxmljs is used to parse untrusted XML. Because the project has little recent maintenance and no release yet addressing the issue, the safest path for many teams is to stop parsing untrusted XML with that library and either sandbox the parsing or replace the library with a maintained alternative. The authoritative project discussion and the PoC live in the libxmljs GitHub issue linked above.