VYPR
High severityNVD Advisory· Published Feb 21, 2011· Updated Apr 29, 2026

CVE-2011-0448

CVE-2011-0448

Description

Ruby on Rails 3.0.x before 3.0.4 does not ensure that arguments to the limit function specify integer values, which makes it easier for remote attackers to conduct SQL injection attacks via a non-numeric argument.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
activerecordRubyGems
>= 3.0.0, < 3.0.43.0.4

Affected products

13
  • Rubyonrails/Rails13 versions
    cpe:2.3:a:rubyonrails:rails:3.0.0:*:*:*:*:*:*:*+ 12 more
    • cpe:2.3:a:rubyonrails:rails:3.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta2:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta3:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta4:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:rc:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.1:pre:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.2:pre:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.4:rc1:*:*:*:*:*:*

Patches

1
354da43ab0a1

limit() should sanitize limit values

https://github.com/rails/railsAaron PattersonDec 7, 2010via ghsa
4 files changed · +55 28
  • activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb+15 15 modified
    @@ -251,6 +251,21 @@ def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
             "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
           end
     
    +      # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
    +      #
    +      # +limit+ may be anything that can evaluate to a string via #to_s. It
    +      # should look like an integer, or a comma-delimited list of integers.
    +      #
    +      # Returns the sanitized limit parameter, either as an integer, or as a
    +      # string which contains a comma-delimited list of integers.
    +      def sanitize_limit(limit)
    +        if limit.to_s =~ /,/
    +          Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
    +        else
    +          Integer(limit)
    +        end
    +      end
    +
           protected
             # Returns an array of record hashes with the column names as keys and
             # column values as values.
    @@ -274,21 +289,6 @@ def delete_sql(sql, name = nil)
               update_sql(sql, name)
             end
     
    -        # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
    -        #
    -        # +limit+ may be anything that can evaluate to a string via #to_s. It
    -        # should look like an integer, or a comma-delimited list of integers.
    -        #
    -        # Returns the sanitized limit parameter, either as an integer, or as a
    -        # string which contains a comma-delimited list of integers.
    -        def sanitize_limit(limit)
    -          if limit.to_s =~ /,/
    -            limit.to_s.split(',').map{ |i| i.to_i }.join(',')
    -          else
    -            limit.to_i
    -          end
    -        end
    -
             # Send a rollback message to all records after they have been rolled back. If rollback
             # is false, only rollback records since the last save point.
             def rollback_transaction_records(rollback) #:nodoc
    
  • activerecord/lib/active_record/relation/query_methods.rb+1 1 modified
    @@ -180,7 +180,7 @@ def build_arel
     
           arel = arel.having(*@having_values.uniq.reject{|h| h.blank?}) unless @having_values.empty?
     
    -      arel = arel.take(@limit_value) if @limit_value
    +      arel = arel.take(connection.sanitize_limit(@limit_value)) if @limit_value
           arel = arel.skip(@offset_value) if @offset_value
     
           arel = arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
    
  • activerecord/test/cases/adapter_test.rb+0 12 modified
    @@ -141,16 +141,4 @@ def test_foreign_key_violations_are_translated_to_specific_exception
           end
         end
       end
    -
    -  def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
    -    sql_inject = "1 select * from schema"
    -    assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject))
    -    assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
    -  end
    -
    -  def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
    -    sql_inject = "1, 7 procedure help()"
    -    assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject))
    -    assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
    -  end
     end
    
  • activerecord/test/cases/base_test.rb+39 0 modified
    @@ -48,6 +48,45 @@ class Boolean < ActiveRecord::Base; end
     class BasicsTest < ActiveRecord::TestCase
       fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts
     
    +  def test_limit_with_comma
    +    assert_nothing_raised do
    +      Topic.limit("1,2").all
    +    end
    +  end
    +
    +  def test_limit_without_comma
    +    assert_nothing_raised do
    +      assert_equal 1, Topic.limit("1").all.length
    +    end
    +
    +    assert_nothing_raised do
    +      assert_equal 1, Topic.limit(1).all.length
    +    end
    +  end
    +
    +  def test_invalid_limit
    +    assert_raises(ArgumentError) do
    +      Topic.limit("asdfadf").all
    +    end
    +  end
    +
    +  def test_limit_should_sanitize_sql_injection_for_limit_without_comas
    +    assert_raises(ArgumentError) do
    +      Topic.limit("1 select * from schema").all
    +    end
    +  end
    +
    +  def test_limit_should_sanitize_sql_injection_for_limit_with_comas
    +    assert_raises(ArgumentError) do
    +      Topic.limit("1, 7 procedure help()").all
    +    end
    +  end
    +
    +  def test_select_symbol
    +    topic_ids = Topic.select(:id).map(&:id).sort
    +    assert_equal Topic.find(:all).map(&:id).sort, topic_ids
    +  end
    +
       def test_table_exists
         assert !NonExistentTable.table_exists?
         assert Topic.table_exists?
    

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

11

News mentions

0

No linked articles in our index yet.