Project

General

Profile

Actions

Feature #19720

closed

Warning for non-linear Regexps

Added by Eregon (Benoit Daloze) over 1 year ago. Updated 12 months ago.

Status:
Rejected
Assignee:
-
Target version:
-
[ruby-core:113819]

Description

I believe the best way to solve ReDoS is to ensure all Regexps used in the process are linear.
Using Regexp.timeout = 5.0 or so does not really prevent ReDoS, given enough requests causing that timeout the servers will still be very unresponsive.

To this purpose, we should make it easy to identify non-linear Regexps and fix them.

I suggest we either use

  1. a performance warning (enabled with Warning[:performance] = true, #19538) or
  2. a new regexp warning category (enabled with Warning[:regexp] = true).

I think we should warn only once per non-linear Regexp, to avoid too many such warnings.
We could warn as soon as the Regexp is created, or on first match.
On first match might makes more sense for Ruby implementations which compile the Regexp lazily (since that is costly during startup), and also avoids warning for Regexps which are never used (which can be good or bad).
OTOH, if the warning is enabled, we could always compile the Regexp eagerly (or at least checks whether it's linear), and that would then provide a better way to guarantee that all Regexps created so far are linear.

Because warnings are easily customizable, it is also possible to e.g. raise/abort on such a warning, if one wants to ensure their application does not use a non-linear Regexp and so cannot be vulnerable to ReDoS:

Warning.extend Module.new {
  def warn(message, category: nil, **)
    raise message if category == :regexp
    super
  end
}

A regexp warning category seems better for that as it makes it easy to filter by category, if a performance warning one would need to match the message which is less clean.

As a note, TruffleRuby already has a similar warning, as a command-line option:

$ truffleruby --experimental-options --warn-truffle-regex-compile-fallback -e 'Gem'
truffleruby-dev/lib/mri/rubygems/version.rb:176: warning: Regexp /\A\s*([0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?)?\s*\z/ at_start=false encoding=US-ASCII requires backtracking and will not match in linear time
truffleruby-dev/lib/mri/rubygems/requirement.rb:105: warning: Regexp /\A\s*(=|!=|>|<|>=|<=|~>)?\s*([0-9]+(?>\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?)\s*\z/ at_start=false encoding=US-ASCII requires backtracking and will not match in linear time

So the warning message could be like
FILE:LINE: warning: Regexp /REGEXP/ requires backtracking and might not match in linear time and might cause ReDoS
or more concise:
FILE:LINE: warning: Regexp /REGEXP/ requires backtracking and might cause ReDoS


Related issues 1 (1 open0 closed)

Related to Ruby master - Feature #19694: Add Regexp#timeout= setterOpenActions
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like1Like0Like0Like0Like0Like0Like0Like0