VYPR
Moderate severityNVD Advisory· Published Jun 29, 2023· Updated Nov 4, 2025

CVE-2023-36617

CVE-2023-36617

Description

A ReDoS issue was discovered in the URI component before 0.12.2 for Ruby. The URI parser mishandles invalid URLs that have specific characters. There is an increase in execution time for parsing strings to URI objects with rfc2396_parser.rb and rfc3986_parser.rb. NOTE: this issue exists becuse of an incomplete fix for CVE-2023-28755. Version 0.10.3 is also a fixed version.

AI Insight

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

A ReDoS vulnerability in Ruby's URI gem (versions before 0.12.2/0.10.3) allows attackers to cause excessive CPU consumption via crafted invalid URLs.

Overview

CVE-2023-36617 is a Regular Expression Denial of Service (ReDoS) vulnerability in the URI component bundled with Ruby. The flaw affects the rfc2396_parser.rb and rfc3986_parser.rb parsers, which mishandle invalid URLs containing specific characters. This causes an exponential increase in execution time when parsing such strings into URI objects [1][3]. Importantly, this issue arises from an incomplete fix for the earlier CVE-2023-28755, meaning the initial patch did not fully address the root cause [3].

Exploitation

An attacker can exploit this vulnerability by supplying a specially crafted, malformed URL to an application that parses user-controlled input as a URI. No authentication or special network position is required; the attack surface includes any service that processes untrusted URLs using the vulnerable URI gem versions (0.12.1 and earlier) [3]. The ReDoS occurs because the regular expressions used in parsing can exhibit catastrophic backtracking when presented with certain character sequences [1].

Impact

Successful exploitation leads to a denial of service condition: the CPU on the affected system becomes heavily utilized while attempting to parse the malformed URL, potentially causing application slowdowns or complete unresponsiveness. This can be leveraged to degrade service availability for legitimate users [1][3].

Mitigation

The Ruby project has released fixed versions: uri gem 0.12.2 and, for older Ruby 3.0 series compatibility, version 0.10.3. Users are advised to update immediately using gem update uri or by pinning "uri", ">= 0.12.2" in their Gemfile. Additionally, Ruby 3.2 users can update to Ruby 3.2.3 to receive the fix [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
uriRubyGems
>= 0.10.1, < 0.10.30.10.3
uriRubyGems
>= 0.12.0, < 0.12.20.12.2
uriRubyGems
>= 0.11.0, < 0.11.20.11.2
uriRubyGems
< 0.10.0.30.10.0.3

Affected products

91

Patches

8
3cd938df20db

Fix quadratic backtracking on invalid port number

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +11 1
  • lib/uri/rfc3986_parser.rb+1 1 modified
    @@ -95,7 +95,7 @@ def default_regexp # :nodoc:
             QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             OPAQUE: /\A(?:[^\/].*)?\z/,
    -        PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
    +        PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
           }
         end
     
    
  • test/uri/test_parser.rb+10 0 modified
    @@ -77,4 +77,14 @@ def test_rfc2822_parse_relative_uri
           end
         end
       end
    +
    +  def test_rfc3986_port_check
    +    pre = ->(length) {"\t" * length + "a"}
    +    uri = URI.parse("http://my.example.com")
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port|
    +      assert_raise(URI::InvalidComponentError) do
    +        uri.port = port
    +      end
    +    end
    +  end
     end
    
9a8e0cc03da9

Fix quadratic backtracking on invalid port number

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +11 1
  • lib/uri/rfc3986_parser.rb+1 1 modified
    @@ -106,7 +106,7 @@ def default_regexp # :nodoc:
             QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             OPAQUE: /\A(?:[^\/].*)?\z/,
    -        PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
    +        PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
           }
         end
     
    
  • test/uri/test_parser.rb+10 0 modified
    @@ -77,4 +77,14 @@ def test_rfc2822_parse_relative_uri
           end
         end
       end
    +
    +  def test_rfc3986_port_check
    +    pre = ->(length) {"\t" * length + "a"}
    +    uri = URI.parse("http://my.example.com")
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port|
    +      assert_raise(URI::InvalidComponentError) do
    +        uri.port = port
    +      end
    +    end
    +  end
     end
    
7e33934c91b7

Fix quadratic backtracking on invalid port number

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +11 1
  • lib/uri/rfc3986_parser.rb+1 1 modified
    @@ -100,7 +100,7 @@ def default_regexp # :nodoc:
             QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             OPAQUE: /\A(?:[^\/].*)?\z/,
    -        PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
    +        PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
           }
         end
     
    
  • test/uri/test_parser.rb+10 0 modified
    @@ -91,4 +91,14 @@ def test_rfc2822_parse_relative_uri
           end
         end
       end
    +
    +  def test_rfc3986_port_check
    +    pre = ->(length) {"\t" * length + "a"}
    +    uri = URI.parse("http://my.example.com")
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port|
    +      assert_raise(URI::InvalidComponentError) do
    +        uri.port = port
    +      end
    +    end
    +  end
     end
    
05b1e7d026b8

Fix quadratic backtracking on invalid port number

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +11 1
  • lib/uri/rfc3986_parser.rb+1 1 modified
    @@ -101,7 +101,7 @@ def default_regexp # :nodoc:
             QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
             OPAQUE: /\A(?:[^\/].*)?\z/,
    -        PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/,
    +        PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
           }
         end
     
    
  • test/uri/test_parser.rb+10 0 modified
    @@ -82,4 +82,14 @@ def test_rfc2822_parse_relative_uri
           end
         end
       end
    +
    +  def test_rfc3986_port_check
    +    pre = ->(length) {"\t" * length + "a"}
    +    uri = URI.parse("http://my.example.com")
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port|
    +      assert_raise(URI::InvalidComponentError) do
    +        uri.port = port
    +      end
    +    end
    +  end
     end
    
4d02315181d8

Fix quadratic backtracking on invalid relative URI

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +14 2
  • lib/uri/rfc2396_parser.rb+2 2 modified
    @@ -491,8 +491,8 @@ def initialize_regexp(pattern)
           ret = {}
     
           # for URI::split
    -      ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    -      ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
     
           # for URI::extract
           ret[:URI_REF]     = Regexp.new(pattern[:URI_REF])
    
  • test/uri/test_parser.rb+12 0 modified
    @@ -65,4 +65,16 @@ def test_split
         assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
         assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
       end
    +
    +  def test_rfc2822_parse_relative_uri
    +    pre = ->(length) {
    +      " " * length + "\0"
    +    }
    +    parser = URI::RFC2396_Parser.new
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri|
    +      assert_raise(URI::InvalidURIError) do
    +        parser.split(uri)
    +      end
    +    end
    +  end
     end
    
38bf797c488b

Fix quadratic backtracking on invalid relative URI

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +14 2
  • lib/uri/rfc2396_parser.rb+2 2 modified
    @@ -497,8 +497,8 @@ def initialize_regexp(pattern)
           ret = {}
     
           # for URI::split
    -      ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    -      ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
     
           # for URI::extract
           ret[:URI_REF]     = Regexp.new(pattern[:URI_REF])
    
  • test/uri/test_parser.rb+12 0 modified
    @@ -70,4 +70,16 @@ def test_split
         assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
         assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
       end
    +
    +  def test_rfc2822_parse_relative_uri
    +    pre = ->(length) {
    +      " " * length + "\0"
    +    }
    +    parser = URI::RFC2396_Parser.new
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri|
    +      assert_raise(URI::InvalidURIError) do
    +        parser.split(uri)
    +      end
    +    end
    +  end
     end
    
70794abc162b

Fix quadratic backtracking on invalid relative URI

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +14 2
  • lib/uri/rfc2396_parser.rb+2 2 modified
    @@ -504,8 +504,8 @@ def initialize_regexp(pattern)
           ret = {}
     
           # for URI::split
    -      ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    -      ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
     
           # for URI::extract
           ret[:URI_REF]     = Regexp.new(pattern[:URI_REF])
    
  • test/uri/test_parser.rb+12 0 modified
    @@ -65,4 +65,16 @@ def test_split
         assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
         assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
       end
    +
    +  def test_rfc2822_parse_relative_uri
    +    pre = ->(length) {
    +      " " * length + "\0"
    +    }
    +    parser = URI::RFC2396_Parser.new
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri|
    +      assert_raise(URI::InvalidURIError) do
    +        parser.split(uri)
    +      end
    +    end
    +  end
     end
    
ba36c8a3ecad

Fix quadratic backtracking on invalid relative URI

https://github.com/ruby/uriNobuyoshi NakadaApr 22, 2023via ghsa
2 files changed · +14 2
  • lib/uri/rfc2396_parser.rb+2 2 modified
    @@ -497,8 +497,8 @@ def initialize_regexp(pattern)
           ret = {}
     
           # for URI::split
    -      ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    -      ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
    +      ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
     
           # for URI::extract
           ret[:URI_REF]     = Regexp.new(pattern[:URI_REF])
    
  • test/uri/test_parser.rb+12 0 modified
    @@ -79,4 +79,16 @@ def test_split
         assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
         assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
       end
    +
    +  def test_rfc2822_parse_relative_uri
    +    pre = ->(length) {
    +      " " * length + "\0"
    +    }
    +    parser = URI::RFC2396_Parser.new
    +    assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri|
    +      assert_raise(URI::InvalidURIError) do
    +        parser.split(uri)
    +      end
    +    end
    +  end
     end
    

Vulnerability mechanics

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

References

21

News mentions

0

No linked articles in our index yet.