CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-5QW5-WF2Q-F538

The Questionable Query: AR-JDBC SQL Injection Deep Dive

Alon Barad
Alon Barad
Software Engineer

Feb 17, 2026·5 min read·40 visits

Executive Summary (TL;DR)

The JRuby database adapter, `activerecord-jdbc-adapter`, failed to safely handle SQL parameter substitution. Attackers can inject a `?` character into a field, which the adapter mistakenly treats as a new placeholder for the *next* value. This allows the second value to be injected inside the first value's quoted string, enabling SQL injection. Patch to version 1.2.8 immediately.

A critical SQL injection vulnerability in the ActiveRecord-JDBC-Adapter allows attackers to manipulate database queries via malformed bind parameters. By injecting specific characters into placeholder values, attackers can trigger a 'double substitution' event, effectively breaking out of quoted strings and executing arbitrary SQL commands on JRuby-based applications.

The Hook: JRuby's Dirty Little Secret

In the world of Ruby on Rails, we take certain things for granted. We assume ActiveRecord will protect us. We assume that when we use Model.where(name: params[:name]), the framework acts as an impenetrable shield against SQL injection. For the most part, we're right. But if you are running Rails on the Java Virtual Machine (JRuby), you rely on a bridge called activerecord-jdbc-adapter (AR-JDBC).

This library is the translator between Ruby's elegant active record pattern and Java's rigid JDBC drivers. It's a critical piece of infrastructure for enterprise Ruby apps. But for years, a logic bomb was ticking inside its string handling code—a flaw so fundamental it turns the concept of 'parameterized queries' on its head.

GHSA-5qw5-wf2q-f538 isn't just a failure of input sanitization; it's a failure of logic. It is a vulnerability that allows an attacker to confuse the database driver about what is code and what is data, simply by asking a question (mark).

The Flaw: The Ouroboros of Substitution

To understand this bug, you have to understand how poor man's parameterized queries work. True prepared statements send the SQL template and the data separately to the database engine. But many adapters, for legacy or compatibility reasons, emulate this by taking the template (SELECT * FROM users WHERE name = ?) and the data (['Alice']), and mashing them together into a string before sending it over the wire.

The flaw in AR-JDBC lay in how it performed this mash-up. The adapter used a loop—specifically Ruby's gsub with a block—to find every ? and replace it with a quoted value. In theory, this is fine. In practice, the implementation suffered from a 'double substitution' or 'nested substitution' issue depending on the specific JRuby/Ruby version behaviors engaged.

When the adapter replaced the first ? with a user-supplied string, it didn't verify if that new string contained a ? of its own. If an attacker supplied Hacker? as the first parameter, the adapter inserted it. Then, due to the iterative nature of how the parameters were processed or subsequent passes in the driver chain, the engine would spot the ? inside the attacker's input and mistake it for the placeholder meant for the second parameter. It's the software equivalent of a snake eating its own tail, effectively allowing data to overwrite the structure of the query.

The Code: When `gsub` Goes Rogue

Let's look at the smoking gun in lib/arjdbc/jdbc/adapter.rb. The developers needed a way to swap binds into the SQL string. They chose this implementation:

# Vulnerable method in lib/arjdbc/jdbc/adapter.rb
def to_sql(sql, binds = [])
  sql = sql.send(:to_sql) if sql.respond_to?(:to_sql)
  return sql if binds.blank?
  
  copy = binds.dup
  # The critical failure:
  sql.gsub('?') { quote(*copy.shift.reverse) }
end

At first glance, this looks like standard Ruby. gsub iterates over matches. copy.shift pulls the next value. quote makes it safe. Done, right? Wrong.

The issue is subtle. If copy.shift returns a string that contains a ?, and the to_sql method logic (or the surrounding infrastructure in older versions) allows for re-scanning or improper cursor management, the ? in the payload consumes the next item in copy.

This means the boundaries between separate bind parameters dissolve. Parameter A can consume Parameter B, injecting Parameter B's raw value into the middle of Parameter A's quoted string.

The Exploit: Inception-Level Injection

Let's weaponize this. Imagine a simple profile update query taking two parameters: a username and a bio.

Target Query:

UPDATE users SET username = ?, bio = ? WHERE id = 123;

The Setup: We need two payloads.

  1. Payload A (The Trap): A string containing a ?. Let's use bad_user?.
  2. Payload B (The Payload): The malicious SQL we want to execute, carefully crafted to break out of quotes. Let's use ', admin=1 --.

The Execution:

  1. The adapter sees the first ? in the SQL template.
  2. It replaces it with the quoted version of Payload A: 'bad_user?'.
  3. The adapter (erroneously) continues scanning or re-scans the string. It finds the ? inside 'bad_user?'.
  4. It thinks, "Ah, another placeholder!" and grabs the next bind value (Payload B).
  5. It shoves Payload B inside the quotes of Payload A.

The Resulting SQL:

UPDATE users SET username = 'bad_user', admin=1 --'', bio = ...

See what happened? The injected ? acted as a portal. The second payload landed inside the string literal of the first, closing the quote (') early and injecting admin=1. The rest of the query (bio = ...) is commented out by the --. We just escalated privileges.

The Fix: Stop Using Regex for Parsing

The fix for this is simple in principle but requires discipline: Do not use simple string replacement for SQL generation. The maintainers patched this in version 1.2.8.

The remediation strategy involves upgrading the gem. If you are stuck on a legacy version of JRuby or Rails, you are in dangerous waters. The patched versions likely move away from naive gsub usage or implement a scanner that is strictly position-aware, ensuring that replaced text is never eligible for future replacement passes.

> [!NOTE] > Developer Lesson: If you find yourself writing a regex to parse or modify SQL, stop. You are almost certainly creating a vulnerability. Use the tokenizer or parser provided by your database driver, or ensure your replacement logic consumes the template linearly without backtracking.

Official Patches

GitHubComparison view of the fix

Technical Appendix

CVSS Score
8.8/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:P
EPSS Probability
0.10%
Top 100% most exploited

Affected Systems

JRuby applications using ActiveRecordactiverecord-jdbc-adapter < 1.2.8

Affected Versions Detail

Product
Affected Versions
Fixed Version
activerecord-jdbc-adapter
JRuby
< 1.2.81.2.8
AttributeDetail
Attack VectorNetwork (Remote)
CVSS v4.08.8 (High)
CWE IDCWE-89 (SQL Injection)
PlatformJRuby / Java
Componentlib/arjdbc/jdbc/adapter.rb
Exploit StatusPoC Available (Theoretical)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.006Command and Scripting Interpreter: Python
Execution
CWE-89
SQL Injection

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

Known Exploits & Detection

GitHub IssueOriginal discussion and discovery of the flaw

Vulnerability Timeline

Vulnerability reported in GitHub Issue #322
2013-02-05
Approximate release of fixed version 1.2.8
2013-02-01
Advisory formally published in GHSA database
2026-01-16

References & Sources

  • [1]GitHub Advisory
  • [2]OSV Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 20 hours ago•CVE-2026-58197
8.8

CVE-2026-58197: Host Escape and Lateral Movement via Insecure Container Network Defaults in ToolHive

A high-severity access control vulnerability in ToolHive CLI before v0.30.1 and ToolHive Studio before v0.38.0 allows local containerized MCP servers to bypass network isolation. This enables malicious workloads to establish TCP/IP connections to administrative and control plane endpoints exposed on the host loopback interface.

Amit Schendel
Amit Schendel
7 views•8 min read
•about 21 hours ago•CVE-2026-63405
5.9

CVE-2026-63405: Insufficient Verification of Data Authenticity in AnyCable Pusher REST API

AnyCable is a real-time communication server. Prior to version 1.6.15, its Pusher-compatible REST API suffered from an authentication bypass vulnerability because it failed to verify that the request body matched the signature-validated body_md5 parameter. This allows attackers to perform replay attacks with modified body contents.

Amit Schendel
Amit Schendel
7 views•5 min read
•about 22 hours ago•CVE-2026-64847
6.8

CVE-2026-64847: Indefinite Denial of Service via Undrained Stderr in AnyIO Process Pool Workers

A denial-of-service vulnerability exists in AnyIO prior to version 4.14.2. Standard error streams of process-pool workers are connected to an operating system pipe that is never drained by the parent process. This allows a worker to fill the pipe buffer and deadlock indefinitely.

Amit Schendel
Amit Schendel
7 views•6 min read
•about 23 hours ago•CVE-2026-63349
7.0

CVE-2026-63349: Privilege Dropping Bypass and Denial of Service in AnyIO Subprocess Module

CVE-2026-63349 is a critical privilege-dropping bypass vulnerability in the AnyIO asynchronous framework (versions 4.14.0 and 4.14.1) on POSIX platforms. Due to a variable assignment typo, supplementary groups specified by the developer are not correctly propagated to the execution backend, resulting in subprocesses retaining the parent process's elevated supplementary group permissions.

Alon Barad
Alon Barad
10 views•5 min read
•about 24 hours ago•CVE-2026-63406
5.9

CVE-2026-63406: Information Disclosure via Insecure Telemetry and Hardcoded Credentials in AnyCable-Go

CVE-2026-63406 is an information disclosure vulnerability in AnyCable-go prior to version 1.6.15. The built-in telemetry client is enabled by default with a hardcoded public authentication token ('secret'). This client digests highly sensitive configuration parameters and command-line arguments, including JWT secrets and RPC secrets, into a stable SHA-256 fingerprint. This fingerprint is sent over public networks, exposing those administrative secrets to offline dictionary and brute-force attacks if intercepted.

Alon Barad
Alon Barad
7 views•5 min read
•1 day ago•CVE-2026-84992
6.1

CVE-2026-84992: Cross-Site Scripting (XSS) via Fenced Code Block Parsing in md-editor-v3

CVE-2026-84992 is a Cross-Site Scripting (XSS) vulnerability affecting md-editor-v3 before version 6.5.4. It occurs because the fenced-code block language parser directly interpolates unescaped language metadata into unquoted HTML attributes inside the custom rendering callback. This bypasses the built-in XSSPlugin which runs during the parsing phase, before rendering.

Amit Schendel
Amit Schendel
9 views•6 min read