Entity expansion DoS vulnerability in REXML (XML bomb, CVE-2013-1821)
Posted by usa on 22 Feb 2013
Unrestricted entity expansion can lead to a DoS vulnerability in REXML. This vulnerability has been assigned the CVE identifier CVE-2013-1821. We strongly recommend to upgrade ruby.
Details
When reading text nodes from an XML document, the REXML parser can be coerced in to allocating extremely large string objects which can consume all of the memory on a machine, causing a denial of service.
Impacted code will look something like this:
document = REXML::Document.new some_xml_doc
document.root.textWhen the `text` method is called, entities will be expanded. An attacker can send a relatively small XML document that, when the entities are resolved, will consume extreme amounts of memory on the target system.
Note that this attack is similar to, but different from the Billion Laughs attack. This is also related to CVE-2013-1664 of Python.
All users running an affected release should either upgrade or use one of the workarounds immediately.
Workarounds
If you cannot upgrade Ruby, use this monkey patch as a workaround:
class REXML::Document
@@entity_expansion_text_limit = 10_240
def self.entity_expansion_text_limit=( val )
@@entity_expansion_text_limit = val
end
def self.entity_expansion_text_limit
@@entity_expansion_text_limit
end
end
class REXML::Text
def self.unnormalize(string, doctype=nil, filter=nil, illegal=nil)
sum = 0
string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) {
s = self.expand($&, doctype, filter)
if sum + s.bytesize > REXML::Document.entity_expansion_text_limit
raise "entity expansion has grown too large"
else
sum += s.bytesize
end
s
}
end
def self.expand(ref, doctype, filter)
if ref[1] == ?#
if ref[2] == ?x
[ref[3...-1].to_i(16)].pack('U*')
else
[ref[2...-1].to_i].pack('U*')
end
elsif ref == '&'
'&'
elsif filter and filter.include?( ref[1...-1] )
ref
elsif doctype
doctype.entity( ref[1...-1] ) or ref
else
entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ]
entity_value ? entity_value.value : ref
end
end
endThis monkey patch will limit the size of the entity substitutions to 10k per node. REXML already defaults to only allow 10000 entity substitutions per document, so the maximum amount of text that can be generated by entity substitution will be around 98 megabytes.
Affected versions
- All ruby 1.9 versions prior to ruby 1.9.3 patchlevel 392
- All ruby 2.0 versions prior to ruby 2.0.0 patchlevel 0
- prior to trunk revision 39384
Credits
Thanks to Ben Murphy for reporting this issue.
History
- Added about CVE number at 2013-03-11 07:45:00 (UTC)
- Originally published at 2013-02-22 12:00:00 (UTC)
Recent News
Ruby 3.2.10 Released
Ruby 3.2.10 has been released.
Posted by hsbt on 14 Jan 2026
Ruby 4.0.1 Released
Ruby 4.0.1 has been released.
Posted by k0kubun on 13 Jan 2026
Ruby 4.0.0 Released
We are pleased to announce the release of Ruby 4.0.0. Ruby 4.0 introduces “Ruby Box” and “ZJIT”, and adds many improvements.
Posted by naruse on 25 Dec 2025
A New Look for Ruby's Documentation
Following the ruby-lang.org redesign, we have more news to celebrate Ruby’s 30th anniversary: docs.ruby-lang.org has a completely new look with Aliki—RDoc’s new default theme.
Posted by Stan Lo on 23 Dec 2025