VYPR
High severityNVD Advisory· Published Apr 25, 2013· Updated Apr 29, 2026

CVE-2013-0175

CVE-2013-0175

Description

multi_xml gem 0.5.2 for Ruby, as used in Grape before 0.2.6 and possibly other products, does not properly restrict casts of string values, which allows remote attackers to conduct object-injection attacks and execute arbitrary code, or cause a denial of service (memory and CPU consumption) involving nested XML entity references, by leveraging support for (1) YAML type conversion or (2) Symbol type conversion, a similar vulnerability to CVE-2013-0156.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
multi_xmlRubyGems
< 0.5.20.5.2

Affected products

13
  • cpe:2.3:a:erik_michaels-ober:multi_xml:0.5.2:*:*:*:*:*:*:*
  • Grape Project/Grape12 versions
    cpe:2.3:a:grape_project:grape:0.1.0:*:*:*:*:*:*:*+ 11 more
    • cpe:2.3:a:grape_project:grape:0.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.1.3:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.1.4:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.1.5:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.1:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.2:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.3:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.4:*:*:*:*:*:*:*
    • cpe:2.3:a:grape_project:grape:0.2.5:*:*:*:*:*:*:*

Patches

1
c94b136d0682

Merge pull request #34 from nate/hotfix/remove-ability-to-parse-symbols-and-yaml

https://github.com/sferik/multi_xmlErik Michaels-OberJan 11, 2013via ghsa
5 files changed · +68 17
  • CONTRIBUTING.md+1 1 modified
    @@ -39,7 +39,7 @@ Ideally, a bug report should include a pull request with failing specs.
     7. Run `open coverage/index.html`. If your changes are not completely covered
        by your tests, return to step 3.
     8. Add documentation for your feature or bug fix.
    -9. Run `bundle exec rake yard`. If your changes are not 100% documented, go
    +9. Run `bundle exec rake doc:yard`. If your changes are not 100% documented, go
        back to step 8.
     10. Add, commit, and push your changes.
     11. [Submit a pull request.][pr]
    
  • lib/multi_xml.rb+23 6 modified
    @@ -7,6 +7,11 @@
     
     module MultiXml
       class ParseError < StandardError; end
    +  class DisallowedTypeError < StandardError
    +    def initialize(type)
    +      super "Disallowed type attribute: #{type.inspect}"
    +    end
    +  end
     
       REQUIREMENT_MAP = [
         ['ox', :ox],
    @@ -54,6 +59,8 @@ class ParseError < StandardError; end
         'Hash'       => 'hash'
       } unless defined?(TYPE_NAMES)
     
    +  DISALLOWED_XML_TYPES = %w(symbol yaml)
    +
       class << self
         # Get the current parser class.
         def parser
    @@ -105,6 +112,8 @@ def parser=(new_parser)
         # <b>Options</b>
         #
         # <tt>:symbolize_keys</tt> :: If true, will use symbols instead of strings for the keys.
    +    #
    +    # <tt>:disallowed_types</tt> :: Types to disallow from being typecasted. Defaults to `['yaml', 'symbol']`. Use `[]` to allow all types.
         def parse(xml, options={})
           xml ||= ''
     
    @@ -116,7 +125,9 @@ def parse(xml, options={})
             return {} if char.nil?
             xml.ungetc(char)
     
    -        hash = typecast_xml_value(undasherize_keys(parser.parse(xml))) || {}
    +        hash = typecast_xml_value(undasherize_keys(parser.parse(xml)), options[:disallowed_types]) || {}
    +      rescue DisallowedTypeError
    +        raise
           rescue parser.parse_error => error
             raise ParseError, error.to_s, error.backtrace
           end
    @@ -191,9 +202,15 @@ def undasherize_keys(params)
           end
         end
     
    -    def typecast_xml_value(value)
    +    def typecast_xml_value(value, disallowed_types=nil)
    +      disallowed_types ||= DISALLOWED_XML_TYPES
    +
           case value
           when Hash
    +        if value.include?('type') && !value['type'].is_a?(Hash) && disallowed_types.include?(value['type'])
    +          raise DisallowedTypeError, value['type']
    +        end
    +
             if value['type'] == 'array'
     
               # this commented-out suggestion helps to avoid the multiple attribute
    @@ -216,9 +233,9 @@ def typecast_xml_value(value)
               else
                 case entries
                 when Array
    -              entries.map {|entry| typecast_xml_value(entry)}
    +              entries.map {|entry| typecast_xml_value(entry, disallowed_types)}
                 when Hash
    -              [typecast_xml_value(entries)]
    +              [typecast_xml_value(entries, disallowed_types)]
                 else
                   raise "can't typecast #{entries.class.name}: #{entries.inspect}"
                 end
    @@ -252,7 +269,7 @@ def typecast_xml_value(value)
               nil
             else
               xml_value = value.inject({}) do |hash, (k, v)|
    -            hash[k] = typecast_xml_value(v)
    +            hash[k] = typecast_xml_value(v, disallowed_types)
                 hash
               end
     
    @@ -261,7 +278,7 @@ def typecast_xml_value(value)
               xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
             end
           when Array
    -        value.map!{|i| typecast_xml_value(i)}
    +        value.map!{|i| typecast_xml_value(i, disallowed_types)}
             value.length > 1 ? value : value.first
           when String
             value
    
  • Rakefile+1 1 modified
    @@ -10,7 +10,7 @@ task :default => :spec
     namespace :doc do
       require 'yard'
       YARD::Rake::YardocTask.new do |task|
    -    task.files   = ['LICENSE.md', 'lib/**/*.rb']
    +    task.files   = ['lib/**/*.rb', '-', 'LICENSE.md']
         task.options = [
           '--no-private',
           '--protected',
    
  • README.md+8 4 modified
    @@ -20,16 +20,20 @@ use it like so:
     ```ruby
     require 'multi_xml'
     
    -MultiXml.parser = :ox MultiXml.parser = MultiXml::Parsers::Ox # Same as above
    +MultiXml.parser = :ox
    +MultiXml.parser = MultiXml::Parsers::Ox # Same as above
     MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Ox
     
    -MultiXml.parser = :libxml MultiXml.parser = MultiXml::Parsers::Libxml # Same as above
    +MultiXml.parser = :libxml
    +MultiXml.parser = MultiXml::Parsers::Libxml # Same as above
     MultiXml.parse('<tag>This is the contents</tag>') # Parsed using LibXML
     
    -MultiXml.parser = :nokogiri MultiXml.parser = MultiXml::Parsers::Nokogiri # Same as above
    +MultiXml.parser = :nokogiri
    +MultiXml.parser = MultiXml::Parsers::Nokogiri # Same as above
     MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Nokogiri
     
    -MultiXml.parser = :rexml MultiXml.parser = MultiXml::Parsers::Rexml # Same as above
    +MultiXml.parser = :rexml
    +MultiXml.parser = MultiXml::Parsers::Rexml # Same as above
     MultiXml.parse('<tag>This is the contents</tag>') # Parsed using REXML
     ```
     The `parser` setter takes either a symbol or a class (to allow for custom XML
    
  • spec/parser_shared_example.rb+35 5 modified
    @@ -323,12 +323,26 @@
               @xml = "<tag type=\"yaml\">--- \n1: returns an integer\n:message: Have a nice day\narray: \n- has-dashes: true\n  has_underscores: true\n</tag>"
             end
     
    -        it "returns a Hash" do
    -          expect(MultiXml.parse(@xml)['tag']).to be_a(Hash)
    +        it "raises MultiXML::DisallowedTypeError by default" do
    +          expect{ MultiXml.parse(@xml)['tag'] }.to raise_error(MultiXml::DisallowedTypeError)
             end
     
    -        it "returns the correctly parsed YAML" do
    -          expect(MultiXml.parse(@xml)['tag']).to eq({:message => "Have a nice day", 1 => "returns an integer", "array" => [{"has-dashes" => true, "has_underscores" => true}]})
    +        it "returns the correctly parsed YAML when the type is allowed" do
    +          expect(MultiXml.parse(@xml, :disallowed_types => [])['tag']).to eq({:message => "Have a nice day", 1 => "returns an integer", "array" => [{"has-dashes" => true, "has_underscores" => true}]})
    +        end
    +      end
    +
    +      context "with an attribute type=\"symbol\"" do
    +        before do
    +          @xml = "<tag type=\"symbol\">my_symbol</tag>"
    +        end
    +
    +        it "raises MultiXML::DisallowedTypeError" do
    +          expect{ MultiXml.parse(@xml)['tag'] }.to raise_error(MultiXml::DisallowedTypeError)
    +        end
    +
    +        it "returns the correctly parsed Symbol when the type is allowed" do
    +          expect(MultiXml.parse(@xml, :disallowed_types => [])['tag']).to eq(:my_symbol)
             end
           end
     
    @@ -418,7 +432,7 @@
             end
           end
     
    -      %w(integer boolean date datetime yaml file).each do |type|
    +      %w(integer boolean date datetime file).each do |type|
             context "with an empty attribute type=\"#{type}\"" do
               before do
                 @xml = "<tag type=\"#{type}\"/>"
    @@ -430,6 +444,22 @@
             end
           end
     
    +      %w{yaml symbol}.each do |type|
    +        context "with an empty attribute type=\"#{type}\"" do
    +          before do
    +            @xml = "<tag type=\"#{type}\"/>"
    +          end
    +
    +          it "raises MultiXml::DisallowedTypeError by default" do
    +            expect{ MultiXml.parse(@xml)['tag']}.to raise_error(MultiXml::DisallowedTypeError)
    +          end
    +
    +          it "returns nil when the type is allowed" do
    +            expect(MultiXml.parse(@xml, :disallowed_types => [])['tag']).to be_nil
    +          end
    +        end
    +      end
    +
           context "with an empty attribute type=\"array\"" do
             before do
               @xml = '<tag type="array"/>'
    

Vulnerability mechanics

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

References

10

News mentions

0

No linked articles in our index yet.