VYPR
Moderate severityNVD Advisory· Published May 16, 2024· Updated Nov 3, 2025

REXML contains a denial of service vulnerability

CVE-2024-35176

Description

REXML is an XML toolkit for Ruby. The REXML gem before 3.2.6 has a denial of service vulnerability when it parses an XML that has many <s in an attribute value. Those who need to parse untrusted XMLs may be impacted to this vulnerability. The REXML gem 3.2.7 or later include the patch to fix this vulnerability. As a workaround, don't parse untrusted XMLs.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

REXML gem before 3.2.7 has a denial of service vulnerability when parsing XML with many `<` characters in attribute values.

Vulnerability

Overview

CVE-2024-35176 is a denial of service (DoS) vulnerability in the REXML XML toolkit for Ruby. The vulnerability exists in versions of the REXML gem prior to 3.2.7 [1]. The root cause is inefficient handling of attribute values containing many < characters during XML parsing. When the parser encounters such input, it can become stuck processing the malformed attribute, leading to excessive resource consumption [2].

Attack

Vector

An attacker can exploit this vulnerability by providing a crafted XML document that includes attribute values with a large number of < characters [1]. No authentication or special network position is required, as any application parsing untrusted XML with REXML is susceptible. The attack surface is broad, affecting any Ruby application that accepts user-supplied XML input [4].

Impact

Successful exploitation results in a denial of service condition. The parser can consume excessive CPU time, potentially causing the application to become unresponsive or crash [4]. This can be used to disrupt services that rely on REXML for XML processing, impacting availability.

Mitigation

The vulnerability is patched in REXML gem version 3.2.7 or later [1]. Users are strongly recommended to upgrade immediately. If upgrading is not possible, the only workaround is to avoid parsing untrusted XML [1]. Users of end-of-life Ruby versions should be aware of compatibility limitations [3].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
rexmlRubyGems
< 3.2.73.2.7

Affected products

108

Patches

1
4325835f92f3

Read quoted attributes in chunks (#126)

https://github.com/ruby/rexmlNobuyoshi NakadaMay 16, 2024via ghsa
4 files changed · +46 15
  • Gemfile+1 0 modified
    @@ -10,4 +10,5 @@ group :development do
       gem "bundler"
       gem "rake"
       gem "test-unit"
    +  gem "test-unit-ruby-core"
     end
    
  • lib/rexml/parsers/baseparser.rb+10 10 modified
    @@ -628,17 +628,17 @@ def parse_attributes(prefixes, curr_ns)
                   message = "Missing attribute equal: <#{name}>"
                   raise REXML::ParseException.new(message, @source)
                 end
    -            unless match = @source.match(/(['"])(.*?)\1\s*/um, true)
    -              if match = @source.match(/(['"])/, true)
    -                message =
    -                  "Missing attribute value end quote: <#{name}>: <#{match[1]}>"
    -                raise REXML::ParseException.new(message, @source)
    -              else
    -                message = "Missing attribute value start quote: <#{name}>"
    -                raise REXML::ParseException.new(message, @source)
    -              end
    +            unless match = @source.match(/(['"])/, true)
    +              message = "Missing attribute value start quote: <#{name}>"
    +              raise REXML::ParseException.new(message, @source)
    +            end
    +            quote = match[1]
    +            value = @source.read_until(quote)
    +            unless value.chomp!(quote)
    +              message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
    +              raise REXML::ParseException.new(message, @source)
                 end
    -            value = match[2]
    +            @source.match(/\s*/um, true)
                 if prefix == "xmlns"
                   if local_part == "xml"
                     if value != "http://www.w3.org/XML/1998/namespace"
    
  • lib/rexml/source.rb+24 5 modified
    @@ -65,7 +65,11 @@ def encoding=(enc)
           encoding_updated
         end
     
    -    def read
    +    def read(term = nil)
    +    end
    +
    +    def read_until(term)
    +      @scanner.scan_until(Regexp.union(term)) or @scanner.rest
         end
     
         def ensure_buffer
    @@ -158,16 +162,31 @@ def initialize(arg, block_size=500, encoding=nil)
           end
         end
     
    -    def read
    +    def read(term = nil)
           begin
    -        @scanner << readline
    +        @scanner << readline(term)
             true
           rescue Exception, NameError
             @source = nil
             false
           end
         end
     
    +    def read_until(term)
    +      pattern = Regexp.union(term)
    +      data = []
    +      begin
    +        until str = @scanner.scan_until(pattern)
    +          @scanner << readline(term)
    +        end
    +      rescue EOFError
    +        @scanner.rest
    +      else
    +        read if @scanner.eos? and !@source.eof?
    +        str
    +      end
    +    end
    +
         def ensure_buffer
           read if @scanner.eos? && @source
         end
    @@ -218,8 +237,8 @@ def current_line
         end
     
         private
    -    def readline
    -      str = @source.readline(@line_break)
    +    def readline(term = nil)
    +      str = @source.readline(term || @line_break)
           if @pending_buffer
             if str.nil?
               str = @pending_buffer
    
  • test/test_document.rb+11 0 modified
    @@ -1,8 +1,12 @@
     # -*- coding: utf-8 -*-
     # frozen_string_literal: false
     
    +require 'core_assertions'
    +
     module REXMLTests
       class TestDocument < Test::Unit::TestCase
    +    include Test::Unit::CoreAssertions
    +
         def test_version_attributes_to_s
           doc = REXML::Document.new(<<~eoxml)
             <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    @@ -198,6 +202,13 @@ def test_xml_declaration_standalone
           assert_equal('no', doc.stand_alone?, bug2539)
         end
     
    +    def test_gt_linear_performance
    +      seq = [10000, 50000, 100000, 150000, 200000]
    +      assert_linear_performance(seq) do |n|
    +        REXML::Document.new('<test testing="' + ">" * n + '"></test>')
    +      end
    +    end
    +
         class WriteTest < Test::Unit::TestCase
           def setup
             @document = REXML::Document.new(<<-EOX)
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.