In late 2022, a significant vulnerability was found in ActiveRecord, the default Object Relational Mapper (ORM) for Ruby on Rails, specifically in its PostgreSQL adapter. If exploited, the bug can lead to severe Denial of Service (DoS) conditions under certain queries. This vulnerability — tracked as CVE-2022-44566 — affected a simple and common codepath, and resolving it involved subtle changes in how type conversions are handled.
In this exclusive long read, we’ll break down the CVE, walk through the underlying issue with code snippets, reference the original advisories, and show how an attacker might exploit this bug. All in plain language for developers and sysadmins alike.
7..4.1 and 6.1.7.1
- CVE Page: NIST NVD - CVE-2022-44566
- Advisory: GitHub Security Advisory
This bug occurs when inserting or comparing an out-of-range integer value with a PostgreSQL column using ActiveRecord, causing inefficient query plans that can slow the database to a crawl.
How Did This Happen?
PostgreSQL has several integer types — SMALLINT (16-bit), INTEGER (32-bit), and BIGINT (64-bit). Imagine you have a BIGINT column in your table, but you (or an attacker) send a value that's too large for BIGINT (i.e., outside the range of a 64-bit signed integer).
ActiveRecord’s adapter would upcast the comparison value to numeric, and PostgreSQL, when comparing integers with numerics, cannot use indexes, falling back to a sequential scan — which is orders of magnitude slower for large tables.
Code Example: Before and After
Let's see how this occurs with an example. Suppose you have a users table with an indexed id column of type bigint.
Vulnerable Code (Before Fix)
# ActiveRecord version < 7..4.1
User.where(id: '9223372036854775808') # One more than 64-bit signed max
Fixed Code (After Patch)
After upgrading ActiveRecord, the query optimizer avoids casting and raises an error or handles the value safely, preventing index loss.
Why Is This Dangerous?
If you expose endpoints that take IDs or user-supplied values (for instance: /users/:id), malicious users can send crafted IDs out of range, silently forcing your database to process slow queries on every request:
An attacker can write a simple script
import requests
for i in range(100):
# Large, out-of-range 64-bit signed int
requests.get("https://target.example.com/users/922337203685477580800000000";)
Or, using a tool like curl in a bash loop
for i in {1..500}; do
curl "https://target.example.com/users/9999999999999999999999999"; &
done
If your Rails app is vulnerable, each of these requests may trigger a sequential table scan, eating up your DB resources.
For Rails 6.1: Update to at least version 6.1.7.1
See the official advisory for more information.
Also consider additional input validation on user-supplied IDs, and audit your logs for such misuse patterns.
References
- NIST: CVE-2022-44566
- GitHub Security Advisory: GHSA-q2cw-7hq2-5mrw
- Rails Commit: patch example
- Blog write-up for context: AppSignal Blog
Summary
- CVE-2022-44566 allows remote users to slow your Rails PostgreSQL-backed app just by providing too-big integers.
- It works by confusing the type casting and breaking index use, forcing inefficient sequential table scans.
Timeline
Published on: 02/09/2023 20:15:00 UTC
Last modified on: 02/16/2023 20:22:00 UTC