Paraxial.io for Ruby 1.5.0 Finds Regexps Built From User Input

Paraxial.io, 2026-10-23

Today the Ruby team released Ruby 4.0.9, 3.4.12, and 3.3.13, fixing memory safety bugs in the regular expression engine. GitLab found that specially crafted patterns could corrupt memory while Ruby compiles them, and used that for remote code execution on GitLab servers. The four ids to track are CVE-2026-89078, CVE-2026-93577, CVE-2026-97229, and CVE-2026-110264, all assigned by GitLab, because the Ruby project has not requested its own.

Paraxial.io for Ruby version 1.5.0 is out today with a new cop, Paraxial/DynamicRegexp, which finds the code in your application that reaches these bugs.


Who Is Affected

Only applications that compile a regexp from a string the attacker controls. A pattern written by a developer, however complicated, is not the problem. The reachable paths are:

Regexp.new(params[:query])
Regexp.compile(cookies[:saved_pattern])
Regexp.union(params[:tags])
/#{params[:highlight]}/i

Two defenses that usually work for regular expression problems do not work here. Regexp.timeout guards against a pattern that runs too long, and these bugs corrupt memory while Ruby is still compiling the pattern, before any matching starts. Limiting the length of the pattern does not reliably help either, because some of these are triggered by short patterns.


Using the Cop

Gemfile

gem "paraxial", "~> 1.5.0"

The cop runs on the next paraxial scan, with no configuration needed:

(Rubocop) Regexp compiled from user input causes memory corruption in the regexp engine.
- Path: app/controllers/products_controller.rb
- Line: 31

A literal, a constant, or a pattern wrapped in Regexp.escape is not reported, because the pattern is yours:

Regexp.new('\A[a-z]+\z')
Regexp.new(TITLE_PATTERN, Regexp::IGNORECASE)
Regexp.new(Regexp.escape(params[:query]))

That last line is the fix to reach for if you cannot upgrade Ruby yet. Regexp.escape neutralizes the metacharacters these bugs are reached through, at the cost of a user no longer being able to supply a real pattern.

For an interpolated regexp, the default style reports the ones that read from the request, meaning params, request, or cookies. To report every interpolation, or to turn the cop off, use .paraxial-rubocop.yml:

Paraxial/DynamicRegexp:
  EnforcedStyle: all
Paraxial/DynamicRegexp:
  Enabled: false

A single line is handled with # rubocop:disable Paraxial/DynamicRegexp, which has the advantage of putting the reason next to the code.

Two things to do today. Upgrade to Ruby 4.0.9, 3.4.12, or 3.3.13. Then run a scan and look at what Paraxial/DynamicRegexp reports, because every one of those lines is a place where a stranger writes a program that your server executes, and the regexp engine is only the most recent reason that is a bad idea.


Paraxial.io secures Ruby on Rails applications, helping humans and AI agents ship safely. Contact us today to get started.

Subscribe to stay up to date on new posts.