VYPR
High severityNVD Advisory· Published Feb 9, 2023· Updated Mar 25, 2025

CVE-2022-44566

CVE-2022-44566

Description

A denial of service vulnerability present in ActiveRecord's PostgreSQL adapter <7.0.4.1 and <6.1.7.1. When a value outside the range for a 64bit signed integer is provided to the PostgreSQL connection adapter, it will treat the target column type as numeric. Comparing integer values against numeric values can result in a slow sequential scan resulting in potential Denial of Service.

AI Insight

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

ActiveRecord PostgreSQL adapter Denial of Service via 64-bit integer overflow forcing slow sequential scans.

Vulnerability

Overview

CVE-2022-44566 is a denial of service vulnerability in the PostgreSQL adapter of ActiveRecord, affecting versions prior to 7.0.4.1 and 6.1.7.1. The root cause is that when a value outside the range of a 64-bit signed integer (i.e., greater than 9223372036854775807 or less than -9223372036854775808) is provided to the adapter, PostgreSQL implicitly treats the column type as numeric. Comparing integer or bigint values against numeric values forces a sequential scan instead of using the index, leading to significantly slower queries [1][4].

Exploitation

Details

An attacker can exploit this by crafting a SQL query with an integer literal that exceeds the 64-bit signed range. For example, using 9223372036854775808 in a WHERE clause will cause PostgreSQL to perform a sequential scan on the table, even if an index exists on the column. The official fix adds a check check_int_in_range that raises an IntegerOutOf64BitRange exception when such an out-of-range value is used, unless the configuration option raise_int_wider_than_64bit is set to false [3].

Impact

Successful exploitation can result in a denial of service by consuming excessive database resources due to slow sequential scans. The impact is limited to scenarios where an attacker can influence the integer value used in a query (e.g., through parameter injection or direct SQL input). While no authentication is strictly required, the attacker must have the ability to execute queries on the database [1][4].

Mitigation

The vulnerability is patched in Rails versions 7.0.4.1 and 6.1.7.1, and also backported to the Rails 5.2 LTS branch (version 5.2.8.15) [2]. Users should upgrade their ActiveRecord to the patched version. The fix raises an exception for out-of-range integers, preventing the slow scan behavior. No workaround is provided for unpatched versions other than upgrading.

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
activerecordRubyGems
< 6.1.7.16.1.7.1
activerecordRubyGems
>= 7.0.0, < 7.0.4.17.0.4.1

Affected products

9

Patches

2
4f44aa9d514e

Added integer width check to PostgreSQL::Quoting

https://github.com/rails/railsZack DeveauNov 22, 2022via ghsa
4 files changed · +78 0
  • activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb+26 0 modified
    @@ -4,6 +4,12 @@ module ActiveRecord
       module ConnectionAdapters
         module PostgreSQL
           module Quoting
    +        class IntegerOutOf64BitRange < StandardError
    +          def initialize(msg)
    +            super(msg)
    +          end
    +        end
    +
             # Escapes binary strings for bytea input to the database.
             def escape_bytea(value)
               @connection.escape_bytea(value) if value
    @@ -120,7 +126,27 @@ def lookup_cast_type(sql_type)
                 super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
               end
     
    +          def check_int_in_range(value)
    +            if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
    +              exception = <<~ERROR
    +                Provided value outside of the range of a signed 64bit integer.
    +
    +                PostgreSQL will treat the column type in question as a numeric.
    +                This may result in a slow sequential scan due to a comparison
    +                being performed between an integer or bigint value and a numeric value.
    +
    +                To allow for this potentially unwanted behavior, set
    +                ActiveRecord::Base.raise_int_wider_than_64bit to false.
    +              ERROR
    +              raise IntegerOutOf64BitRange.new exception
    +            end
    +          end
    +
               def _quote(value)
    +            if ActiveRecord::Base.raise_int_wider_than_64bit && value.is_a?(Integer)
    +              check_int_in_range(value)
    +            end
    +
                 case value
                 when OID::Xml::Data
                   "xml '#{quote_string(value.to_s)}'"
    
  • activerecord/lib/active_record/core.rb+7 0 modified
    @@ -163,6 +163,13 @@ def self.configurations
           # to Psych safe_load in the YAML Coder
           mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
     
    +      ##
    +      # :singleton-method:
    +      # Application configurable boolean that denotes whether or not to raise
    +      # an exception when the PostgreSQLAdapter is provided with an integer that is
    +      # wider than signed 64bit representation
    +      mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true
    +
           self.filter_attributes = []
     
           def self.connection_handler
    
  • activerecord/test/cases/adapters/postgresql/quoting_test.rb+28 0 modified
    @@ -8,6 +8,7 @@ class PostgreSQLAdapter
           class QuotingTest < ActiveRecord::PostgreSQLTestCase
             def setup
               @conn = ActiveRecord::Base.connection
    +          @raise_int_wider_than_64bit = ActiveRecord::Base.raise_int_wider_than_64bit
             end
     
             def test_type_cast_true
    @@ -44,6 +45,33 @@ def test_quote_table_name_with_spaces
               value = "user posts"
               assert_equal "\"user posts\"", @conn.quote_table_name(value)
             end
    +
    +        def test_raise_when_int_is_wider_than_64bit
    +          value = 9223372036854775807 + 1
    +          assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
    +            @conn.quote(value)
    +          end
    +
    +          value = -9223372036854775808 - 1
    +          assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
    +            @conn.quote(value)
    +          end
    +        end
    +
    +        def test_do_not_raise_when_int_is_not_wider_than_64bit
    +          value = 9223372036854775807
    +          assert_equal "9223372036854775807", @conn.quote(value)
    +
    +          value = -9223372036854775808
    +          assert_equal "-9223372036854775808", @conn.quote(value)
    +        end
    +
    +        def test_do_not_raise_when_raise_int_wider_than_64bit_is_false
    +          ActiveRecord::Base.raise_int_wider_than_64bit = false
    +          value = 9223372036854775807 + 1
    +          assert_equal "9223372036854775808", @conn.quote(value)
    +          ActiveRecord::Base.raise_int_wider_than_64bit = @raise_int_wider_than_64bit
    +        end
           end
         end
       end
    
  • railties/test/application/configuration_test.rb+17 0 modified
    @@ -2260,6 +2260,23 @@ class D < C
           assert_equal([Symbol], ActiveRecord::Base.yaml_column_permitted_classes)
         end
     
    +    test "config.active_record.raise_int_wider_than_64bit is true by default" do
    +      app "production"
    +      assert ActiveRecord::Base.raise_int_wider_than_64bit
    +    end
    +
    +    test "config.active_record.raise_int_wider_than_64bit can be configured" do
    +      remove_from_config '.*config\.load_defaults.*\n'
    +
    +      app_file "config/initializers/dont_raise.rb", <<-RUBY
    +        Rails.application.config.active_record.raise_int_wider_than_64bit = false
    +      RUBY
    +
    +      app "production"
    +      assert_not ActiveRecord::Base.raise_int_wider_than_64bit
    +    end
    +
    +
         test "ActiveRecord::Base.has_many_inversing is true by default for new apps" do
           app "development"
     
    
82bcdc011e2f

Added integer width check to PostgreSQL::Quoting

https://github.com/rails/railsZack DeveauNov 21, 2022via ghsa
5 files changed · +85 0
  • activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb+26 0 modified
    @@ -4,6 +4,12 @@ module ActiveRecord
       module ConnectionAdapters
         module PostgreSQL
           module Quoting
    +        class IntegerOutOf64BitRange < StandardError
    +          def initialize(msg)
    +            super(msg)
    +          end
    +        end
    +
             # Escapes binary strings for bytea input to the database.
             def escape_bytea(value)
               @connection.escape_bytea(value) if value
    @@ -16,7 +22,27 @@ def unescape_bytea(value)
               @connection.unescape_bytea(value) if value
             end
     
    +        def check_int_in_range(value)
    +          if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
    +            exception = <<~ERROR
    +              Provided value outside of the range of a signed 64bit integer.
    +
    +              PostgreSQL will treat the column type in question as a numeric.
    +              This may result in a slow sequential scan due to a comparison
    +              being performed between an integer or bigint value and a numeric value.
    +
    +              To allow for this potentially unwanted behavior, set
    +              ActiveRecord.raise_int_wider_than_64bit to false.
    +            ERROR
    +            raise IntegerOutOf64BitRange.new exception
    +          end
    +        end
    +
             def quote(value) # :nodoc:
    +          if ActiveRecord.raise_int_wider_than_64bit && value.is_a?(Integer)
    +            check_int_in_range(value)
    +          end
    +
               case value
               when OID::Xml::Data
                 "xml '#{quote_string(value.to_s)}'"
    
  • activerecord/lib/active_record.rb+8 0 modified
    @@ -347,6 +347,14 @@ def self.global_executor_concurrency # :nodoc:
       singleton_class.attr_accessor :use_yaml_unsafe_load
       self.use_yaml_unsafe_load = false
     
    +  ##
    +  # :singleton-method:
    +  # Application configurable boolean that denotes whether or not to raise
    +  # an exception when the PostgreSQLAdapter is provided with an integer that
    +  # is wider than signed 64bit representation
    +  singleton_class.attr_accessor :raise_int_wider_than_64bit
    +  self.raise_int_wider_than_64bit = true
    +
       ##
       # :singleton-method:
       # Application configurable array that provides additional permitted classes
    
  • activerecord/test/cases/adapters/postgresql/quoting_test.rb+28 0 modified
    @@ -8,6 +8,7 @@ class PostgreSQLAdapter
           class QuotingTest < ActiveRecord::PostgreSQLTestCase
             def setup
               @conn = ActiveRecord::Base.connection
    +          @raise_int_wider_than_64bit = ActiveRecord.raise_int_wider_than_64bit
             end
     
             def test_type_cast_true
    @@ -44,6 +45,33 @@ def test_quote_table_name_with_spaces
               value = "user posts"
               assert_equal "\"user posts\"", @conn.quote_table_name(value)
             end
    +
    +        def test_raise_when_int_is_wider_than_64bit
    +          value = 9223372036854775807 + 1
    +          assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
    +            @conn.quote(value)
    +          end
    +
    +          value = -9223372036854775808 - 1
    +          assert_raise ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange do
    +            @conn.quote(value)
    +          end
    +        end
    +
    +        def test_do_not_raise_when_int_is_not_wider_than_64bit
    +          value = 9223372036854775807
    +          assert_equal "9223372036854775807", @conn.quote(value)
    +
    +          value = -9223372036854775808
    +          assert_equal "-9223372036854775808", @conn.quote(value)
    +        end
    +
    +        def test_do_not_raise_when_raise_int_wider_than_64bit_is_false
    +          ActiveRecord.raise_int_wider_than_64bit = false
    +          value = 9223372036854775807 + 1
    +          assert_equal "9223372036854775808", @conn.quote(value)
    +          ActiveRecord.raise_int_wider_than_64bit = @raise_int_wider_than_64bit
    +        end
           end
         end
       end
    
  • guides/source/configuring.md+6 0 modified
    @@ -1016,6 +1016,12 @@ Defaults to `[Symbol]`. Allows applications to include additional permitted clas
     
     Defaults to `false`. Allows applications to opt into using `unsafe_load` on the `ActiveRecord::Coders::YAMLColumn`.
     
    +#### `config.active_record.raise_int_wider_than_64bit`
    +
    +Defaults to `true`. Determines whether to raise an exception or not when
    +the PostgreSQL adapter is provided an integer that is wider than signed
    +64bit representation.
    +
     #### `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans`
     
     Controls whether the Active Record MySQL adapter will consider all `tinyint(1)` columns as booleans. Defaults to `true`.
    
  • railties/test/application/configuration_test.rb+17 0 modified
    @@ -1711,6 +1711,23 @@ def index
           assert ActiveRecord.use_yaml_unsafe_load
         end
     
    +    test "config.active_record.raise_int_wider_than_64bit is true by default" do
    +      app "production"
    +      assert ActiveRecord.raise_int_wider_than_64bit
    +    end
    +
    +    test "config.active_record.raise_int_wider_than_64bit can be configured" do
    +      remove_from_config '.*config\.load_defaults.*\n'
    +
    +      app_file "config/initializers/dont_raise.rb", <<-RUBY
    +        Rails.application.config.active_record.raise_int_wider_than_64bit = false
    +      RUBY
    +
    +      app "production"
    +      assert_not ActiveRecord.raise_int_wider_than_64bit
    +    end
    +
    +
         test "config.active_record.yaml_column_permitted_classes is [Symbol] by default" do
           app "production"
           assert_equal([Symbol], ActiveRecord.yaml_column_permitted_classes)
    

Vulnerability mechanics

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

References

12

News mentions

0

No linked articles in our index yet.