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



GHSA-PHWJ-RPRQ-35PP

GHSA-PHWJ-RPRQ-35PP: Use-After-Free Vulnerability in Nokogiri XML Attribute Value Modification

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 19, 2026·6 min read·29 visits

Executive Summary (TL;DR)

A use-after-free vulnerability in the Nokogiri gem's CRuby extension allows remote attackers to trigger process crashes or memory corruption when updating XML attribute values.

A use-after-free (UAF) vulnerability exists in the CRuby native extension of the Nokogiri gem when updating XML attribute values. If child nodes of an XML attribute are wrapped by Ruby objects prior to setting the attribute's value, the underlying C memory structures are freed while the Ruby wrapper retains a dangling pointer. This results in memory corruption, invalid pointer dereferences, and application crashes during execution or garbage collection.

Vulnerability Overview

The Nokogiri library is a widely used Ruby gem for parsing, manipulating, and querying XML and HTML documents. To achieve high performance, Nokogiri relies on a native C extension that acts as a wrapper around the libxml2 library. This architecture divides application state into two distinct spaces: managed Ruby heap memory and unmanaged native system memory managed by libxml2.

The vulnerability designated as GHSA-PHWJ-RPRQ-35PP is a use-after-free (UAF) flaw classified under CWE-416. It resides within the native extension layer of Nokogiri that manages XML attribute nodes. Specifically, the flaw exists within the implementation of attribute value updates, where native memory deallocation is executed without checking the state of corresponding Ruby wrappers.

The attack surface is exposed when a Ruby application processes untrusted XML data, instantiates Ruby-side wrappers for the child nodes of XML attributes, and subsequently modifies those attributes. The resulting memory instability can be exploited to cause immediate application crashes, presenting a localized denial-of-service (DoS) vector.

Root Cause Analysis

The root cause of GHSA-PHWJ-RPRQ-35PP lies in the lifecycle mismatch between native libxml2 structures and Ruby proxy objects. When an XML attribute (xmlAttr) contains a text value, libxml2 represents this value internally as a linked list of child nodes (xmlNode). When a Ruby developer calls Nokogiri::XML::Attr#child or Attr#children, Nokogiri instantiates a Ruby object proxy wrapping the underlying native xmlNode structure.

To maintain a mapping between native nodes and their Ruby proxies, Nokogiri utilizes the _private field of the libxml2 xmlNode structure. This field contains a pointer back to the Ruby wrapper. This back-reference allows Nokogiri to return the same Ruby object when the same native node is accessed multiple times, preventing object duplication.

In vulnerable versions of Nokogiri, when the #value= or #content= methods are invoked on an attribute, the native C function set_value is executed in ext/nokogiri/xml_attr.c. This function immediately calls xmlFreeNodeList(attr->children) to clear the existing attribute contents from memory. The function fails to inspect the _private field of the child nodes being deallocated.

Consequently, if a child node has been wrapped in a Ruby object, the native node memory is freed, but the Ruby proxy object remains alive and active on the Ruby heap. The Ruby wrapper holds a now-dangling pointer to the deallocated C structure. Any subsequent read, write, or traversal operation involving this wrapper dereferences the invalid pointer, resulting in memory corruption or process termination.

Code-Level Patch Analysis

To understand the mechanical differences between the vulnerable and patched states, analyze the implementation of the attribute update process in ext/nokogiri/xml_attr.c. In the vulnerable code, the deallocation phase unconditionally cleans the linked list of child nodes.

The patch introduced in version 1.19.4 replaces the raw set_value function with noko_xml_attr_set_value and introduces a safety loop to inspect each child node before any deallocation occurs.

/* Unlink and pin any wrapped children */
xmlNode *cur = attr->children;
xmlNode *next;
 
while (cur) {
  next = cur->next;
  if (cur->_private) {
    xmlUnlinkNode(cur);
    noko_xml_document_pin_node(cur);
  }
  cur = next;
}

The added loop iterates over the linked list of children (attr->children). If cur->_private is evaluated as true, indicating that a Ruby wrapper exists, the code unlinks the node using xmlUnlinkNode(cur). This removes the node from the attribute's child list so that it will not be freed by subsequent mutation functions.

The unlinked node is then passed to noko_xml_document_pin_node(cur). This function registers the node within Nokogiri's document-level node cache. This action pins the node in native memory, ensuring its structure is preserved as long as the document or the corresponding Ruby proxy object exists, successfully eliminating the use-after-free condition.

Exploitation Methodology & Proof of Concept

Exploitation of GHSA-PHWJ-RPRQ-35PP requires a precise sequence of API interactions on a parsed XML structure. The initial prerequisite is the ingestion of an XML document containing an element with at least one attribute. The application must then access the attribute's children to initialize the Ruby proxy wrappers.

The following sequence represents a reliable proof of concept to demonstrate the vulnerability:

require 'nokogiri'
 
doc = Nokogiri::XML("<root target_attr='value_to_leak'/>")
attribute_node = doc.root.attribute("target_attr")
 
# This instantiates the Ruby-land proxy object
dangling_child = attribute_node.child
 
# This frees the native memory behind dangling_child
attribute_node.value = "new_replaced_value"
 
# Trigger Garbage Collection to force marking of the dangling pointer
GC.start(full_mark: true)
 
# Attempting to access the orphaned object triggers a segmentation fault
puts dangling_child.to_s

Upon executing the mutation step (attribute_node.value = "new_replaced_value"), the C memory representing 'value_to_leak' is reclaimed by the operating system allocator. The variable dangling_child continues to point to this address.

When GC.start is called, the Ruby virtual machine traverses active heap references to mark reachable objects. During this phase, or when explicitly invoking methods on dangling_child, the VM attempts to dereference the invalid address, causing an immediate segmentation fault.

Impact Assessment & Risk Vector

The security impact of GHSA-PHWJ-RPRQ-35PP is primarily confined to application availability. An unauthenticated remote attacker who can control XML inputs and influence the application's processing flow to trigger the vulnerable code path can cause the underlying Ruby process to terminate.

In environments running single-process web servers or worker queues, repeated process crashes can lead to a sustained denial-of-service condition. Because Nokogiri is heavily used in background jobs and document processors, this vulnerability presents an easy target for service disruption.

Achieving arbitrary code execution (RCE) via this use-after-free flaw is theoretically possible but highly complex in practice. The attacker would need to execute a precise heap grooming attack to reclaim the freed xmlNode memory allocation with controlled payload data before the pointer is dereferenced. This is difficult because of the asynchronous nature of Ruby's allocator and GC pauses.

The CVSS v4.0 score of 2.3 reflects this limited severity. The low rating is due to the high specificity of the required API usage pattern, which is not a standard pattern in most Nokogiri-based applications.

Mitigation and Defense-in-Depth

The definitive remediation for this vulnerability is to upgrade the Nokogiri dependency to version 1.19.4 or later. This release incorporates the defensive node unlinking and pinning logic in the CRuby native extension. JRuby environments are inherently unaffected as the Java-backed implementation of Nokogiri does not use this C extension.

If an immediate upgrade is not feasible, developers must audit their codebases to eliminate vulnerable API usage patterns. Avoid accessing attribute values via their child nodes. Instead, read and write attribute values using standard string-based interfaces.

# Vulnerable pattern
child_node = attr.child
attr.value = "new"
 
# Safe pattern
attr_value_string = attr.value
attr.value = "new"

To detect instances of this vulnerability dynamically during development, test suites can be executed under the control of AddressSanitizer (ASan). Compiling Ruby and Nokogiri with ASan enabled allows immediate detection of the use-after-free invalid memory read as soon as the attribute value is changed, providing detailed backtraces of the deallocation and access points.

Official Patches

Nokogiri MaintainersRelease comparison and commit logs containing the resolution patch.

Fix Analysis (1)

Technical Appendix

CVSS Score
2.3/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:U

Affected Systems

Nokogiri (CRuby implementations)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Nokogiri
Nokogiri Maintainers
< 1.19.41.19.4
AttributeDetail
CWE IDCWE-416
Vulnerability ClassUse-After-Free (UAF)
CVSS Score2.3 (Low)
Attack VectorNetwork
Exploit StatusProof-of-Concept
KEV StatusNot Listed
Patched Version1.19.4

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Denial of Service
T1203Exploitation for Client Execution
Execution
CWE-416
Use After Free

Referencing memory after it has been freed, which can cause a program to crash, use unexpected values, or execute arbitrary code.

Known Exploits & Detection

GitHub Security AdvisoryVulnerability announcement containing reproduction methodology and code verification.

Vulnerability Timeline

Technical fix committed by Mike Dalessio
2026-06-14
Nokogiri version 1.19.4 is officially released
2026-06-18
GitHub Security Advisory GHSA-PHWJ-RPRQ-35PP is published
2026-06-19

References & Sources

  • [1]GHSA-PHWJ-RPRQ-35PP Security Advisory
  • [2]Nokogiri GitHub Repository
  • [3]Nokogiri 1.19.4 Patch Comparison

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

•6 minutes ago•CVE-2026-69192
7.7

CVE-2026-69192: SSRF Bypass via Parser Differential (Octal vs Decimal) in ip-address JavaScript Library

CVE-2026-69192 is a critical parser differential vulnerability in the 'ip-address' JavaScript library (versions <= 10.3.0). The library parses IPv4 octets containing leading zeros as base-10 (decimal), whereas standard system resolvers and web environments parse them as base-8 (octal). This discrepancy allows remote attackers to bypass SSRF guards and route malicious requests to internal RFC 1918 networks.

Alon Barad
Alon Barad
0 views•6 min read
•about 1 hour ago•CVE-2026-69151
7.6

CVE-2026-69151: Stored Cross-Site Scripting (XSS) in Angular Compiler i18n Pipeline via Event-Handler Attributes

A high-severity security vulnerability has been identified within the Angular compiler's internationalization (i18n) metadata collection and translation pipeline. Angular implements strict defenses against client-side execution injection by validating standard attribute and property bindings. However, when parsing elements containing both i18n translation attributes and inline event-handler elements (such as `i18n-onerror`), the compiler failed to assert the safety of the target attribute. Consequently, compromised or untrusted localization translation source files can supply arbitrary JavaScript payloads that replace static event-handler bindings. This arbitrary code is compiled directly into the localized build bundle and executed dynamically by the web browser, bypassing runtime sanitization, security checks, and standard binding constraints.

Amit Schendel
Amit Schendel
0 views•8 min read
•about 2 hours ago•CVE-2026-69153
6.3

CVE-2026-69153: Arbitrary File Read via Path Traversal in PostCSS

A directory traversal and arbitrary file read vulnerability exists in PostCSS due to an incomplete fix of CVE-2026-45623. When parsing a CSS file containing a sourceMappingURL comment with the 'from' parameter unset, path traversal and absolute path validations are bypassed, enabling attackers to read arbitrary local .map files.

Amit Schendel
Amit Schendel
1 views•5 min read
•about 3 hours ago•CVE-2026-69152
7.5

CVE-2026-69152: Denial of Service via Resource Exhaustion in brace-expansion

CVE-2026-69152 is a high-severity Denial of Service (DoS) vulnerability in brace-expansion that allows remote, unauthenticated attackers to cause a process crash or infinite thread-blocking condition. The vulnerability stems from a complete mitigation bypass of the security checks implemented for CVE-2026-14257.

Alon Barad
Alon Barad
1 views•7 min read
•about 4 hours ago•CVE-2026-68945
8.8

CVE-2026-68945: Cache-Key Ambiguity in Angular HttpTransferCache Leading to State Poisoning

An in-depth technical analysis of CVE-2026-68945, a high-severity security vulnerability in Angular's `@angular/common/http` package. The flaw stems from an ambiguity in how query parameters are serialized to generate cache keys during Server-Side Rendering (SSR) within the `HttpTransferCache` component. By failing to encode delimiters and implicitly coercing arrays to comma-joined strings, the serialization mechanism yields identical cache keys for distinct requests, facilitating State Poisoning and Cross-Request Response Reuse.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 6 hours ago•CVE-2026-43501
9.8

CVE-2026-43501: Heap Out-of-Bounds Write in Linux Kernel IPv6 RPL Segment Routing Header Processing

A critical heap out-of-bounds (OOB) write vulnerability exists in the Linux kernel's IPv6 RPL (Routing Protocol for Low-Power and Lossy Networks) Segment Routing Header (SRH) processing logic. The vulnerability is located within net/ipv6/exthdrs.c, specifically in the ipv6_rpl_srh_rcv function. Under specific circumstances, when a packet containing a compressed RPL Source Routing Header is processed, segment swapping can reduce the common-prefix length, causing the recompressed header to grow. Because the kernel fails to validate available headroom on intermediate segments, a buffer underflow occurs during skb_push. This leads to an integer wrap in the MAC header offset pointer during MAC header rebuilding, causing a 14-byte out-of-bounds memory write roughly 64 KiB past the socket buffer.

Alon Barad
Alon Barad
4 views•10 min read