High severityNVD Advisory· Published Jun 22, 2012· Updated Apr 29, 2026
CVE-2012-2695
CVE-2012-2695
Description
The Active Record component in Ruby on Rails before 3.0.14, 3.1.x before 3.1.6, and 3.2.x before 3.2.6 does not properly implement the passing of request data to a where method in an ActiveRecord class, which allows remote attackers to conduct certain SQL injection attacks via nested query parameters that leverage improper handling of nested hashes, a related issue to CVE-2012-2661.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
activerecordRubyGems | >= 3.0.0.beta, < 3.0.14 | 3.0.14 |
activerecordRubyGems | >= 3.1.0, < 3.1.6 | 3.1.6 |
activerecordRubyGems | >= 3.2.0, < 3.2.6 | 3.2.6 |
activerecordRubyGems | < 2.3.15 | 2.3.15 |
Affected products
74cpe:2.3:a:rubyonrails:rails:3.0.0:*:*:*:*:*:*:*+ 71 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.10:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.10:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.11:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.12:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.12:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.13:rc1:*:*:*:*:*:*
- 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:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.5:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.5:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.6:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.6:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.6:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.7:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.7:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.7:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.8:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.8:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.8:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.8:rc3:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.8:rc4:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:rc3:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:rc4:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.0.9:rc5:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:beta1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc3:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc4:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc5:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc6:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc7:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.0:rc8:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.1:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.1:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.1:rc3:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.2:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.2:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.4:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.4:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.5:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.1.5:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.0:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.0:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.0:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.2:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.2:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.3:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.3:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.3:rc2:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.4:*:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.4:rc1:*:*:*:*:*:*
- cpe:2.3:a:rubyonrails:rails:3.2.5:*:*:*:*:*:*:*
cpe:2.3:a:rubyonrails:ruby_on_rails:*:*:*:*:*:*:*:*+ 1 more
- cpe:2.3:a:rubyonrails:ruby_on_rails:*:*:*:*:*:*:*:*range: <=3.0.13
- cpe:2.3:a:rubyonrails:ruby_on_rails:3.0.4:*:*:*:*:*:*:*
Patches
162f81f4d6b3eFix SQL injection via nested hashes in conditions
2 files changed · +22 −4
activerecord/lib/active_record/base.rb+6 −4 modified@@ -2333,26 +2333,28 @@ def expand_hash_conditions_for_aggregates(attrs) # And for value objects on a composed_of relationship: # { :address => Address.new("123 abc st.", "chicago") } # # => "address_street='123 abc st.' and address_city='chicago'" - def sanitize_sql_hash_for_conditions(attrs, default_table_name = quoted_table_name) + def sanitize_sql_hash_for_conditions(attrs, default_table_name = quoted_table_name, top_level = true) attrs = expand_hash_conditions_for_aggregates(attrs) conditions = attrs.map do |attr, value| table_name = default_table_name - unless value.is_a?(Hash) + if not value.is_a?(Hash) attr = attr.to_s # Extract table name from qualified attribute names. - if attr.include?('.') + if attr.include?('.') and top_level attr_table_name, attr = attr.split('.', 2) attr_table_name = connection.quote_table_name(attr_table_name) else attr_table_name = table_name end attribute_condition("#{attr_table_name}.#{connection.quote_column_name(attr)}", value) + elsif top_level + sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s), false) else - sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s)) + raise ActiveRecord::StatementInvalid end end.join(' AND ')
activerecord/test/cases/finder_test.rb+16 −0 modified@@ -363,6 +363,22 @@ def test_hash_condition_find_malformed } end + def test_hash_condition_find_with_improper_nested_hashes + assert_raise(ActiveRecord::StatementInvalid) { + Company.find(:first, :conditions => { :name => { :companies => { :id => 1 }}}) + } + end + + def test_hash_condition_find_with_dot_in_nested_column_name + assert_raise(ActiveRecord::StatementInvalid) { + Company.find(:first, :conditions => { :name => { "companies.id" => 1 }}) + } + end + + def test_hash_condition_find_with_dot_in_column_name_okay + assert Company.find(:first, :conditions => { "companies.id" => 1 }) + end + def test_hash_condition_find_with_escaped_characters Company.create("name" => "Ain't noth'n like' \#stuff") assert Company.find(:first, :conditions => { :name => "Ain't noth'n like' \#stuff" })
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- groups.google.com/group/rubyonrails-security/msg/aee3413fb038bf56nvdExploitWEB
- github.com/advisories/GHSA-76wq-xw4h-f8wjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-2695ghsaADVISORY
- lists.opensuse.org/opensuse-security-announce/2012-08/msg00002.htmlnvdWEB
- lists.opensuse.org/opensuse-security-announce/2012-08/msg00014.htmlnvdWEB
- lists.opensuse.org/opensuse-security-announce/2012-08/msg00016.htmlnvdWEB
- lists.opensuse.org/opensuse-updates/2012-08/msg00046.htmlnvdWEB
- rhn.redhat.com/errata/RHSA-2013-0154.htmlnvdWEB
- github.com/rails/rails/commit/62f81f4d6b3ee40e9887ffd92ab14714bad93f18ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/activerecord/CVE-2012-2695.ymlghsaWEB
- groups.google.com/g/rubyonrails-security/c/l4L0TEVAz1k/m/Vr84sD9B464JghsaWEB
News mentions
0No linked articles in our index yet.