[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ruby-core
Subject:    [ruby-core:108116] [Ruby master Feature#17837] Add support for Regexp timeouts
From:       "mame (Yusuke Endoh)" <noreply () ruby-lang ! org>
Date:       2022-03-30 1:22:04
Message-ID: redmine.journal-97084.20220330012204.5660 () ruby-lang ! org
[Download RAW message or body]

Issue #17837 has been updated by mame (Yusuke Endoh).


@naruse said "let's try it with Ruby 3.2.0-preview1" so I'll merge my PR soon. 

----------------------------------------
Feature #17837: Add support for Regexp timeouts
https://bugs.ruby-lang.org/issues/17837#change-97084

* Author: sam.saffron (Sam Saffron)
* Status: Open
* Priority: Normal
----------------------------------------
### Background

ReDoS are a very common security issue. At Discourse we have seen a few through the \
years. https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS


In a nutshell there are 100s of ways this can happen in production apps, the key is \
for an attacker (or possibly innocent person) to supply either a problematic Regexp \
or a bad string to test it with.

```
/A(B|C+)+D/ =~ "A" + "C" * 100 + "X"
```

Having a problem Regexp somewhere in a large app is a universal constant, it will \
happen as long as you are using Regexps. 


Currently the only feasible way of supplying a consistent safeguard is by using \
`Thread.raise` and managing all execution. This kind of pattern requires usage of a \
third party implementation. There are possibly issues with jRuby and Truffle when \
taking approaches like this.

### Prior art

.NET provides a `MatchTimeout` property per: \
https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.matchtimeout?view=net-5.0


Java has nothing built in as far as I can tell: \
https://stackoverflow.com/questions/910740/cancelling-a-long-running-regex-match

Node has nothing built in as far as I can tell: \
https://stackoverflow.com/questions/38859506/cancel-regex-match-if-timeout


Golang and Rust uses RE2 which is not vulnerable to DoS by limiting features \
(available in Ruby RE2 gem)

```
irb(main):003:0> r = RE2::Regexp.new('A(B|C+)+D')
=> #<RE2::Regexp /A(B|C+)+D/>
irb(main):004:0> r.match("A" + "C" * 100 + "X")
=> nil
```

### Proposal

Implement `Regexp.timeout` which allow us to specify a global timeout for all Regexp \
operations in Ruby. 

Per Regexp would require massive application changes, almost all web apps would do \
just fine with a 1 second Regexp timeout.

If `timeout` is set to `nil` everything would work as it does today, when set to \
second a "monitor" thread would track running regexps and time them out according to \
the global value.

### Alternatives 

I recommend against a "per Regexp" API as this decision is at the application level. \
You want to apply it to all regular expressions in all the gems you are consuming.

I recommend against a move to RE2 at the moment as way too much would break 


### See also: 

https://people.cs.vt.edu/davisjam/downloads/publications/Davis-Dissertation-2020.pdf
https://levelup.gitconnected.com/the-regular-expression-denial-of-service-redos-cheat-sheet-a78d0ed7d865






-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic