# Regular expression denial of service in ActiveRecord's PostgreSQL Money type

ReDoS in ActiveRecord PostgreSQL Money type regex where overlapping \D* and [\d,]+ quantifiers cause quadratic backtracking on crafted money strings, saturating CPU.

- Payout: hidden
- Severity: medium
- Program: Ruby on Rails
- Found by: dee-see
- Disclosed: 2021-02-11
- CVE: CVE-2021-22880
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/1023899
- Library page: https://bugbountylibrary.com/r/h1%3A1023899
- Tags: area:web domain:web impact:dos kind:bounty platform:hackerone sev:medium tech:ruby technique:source-review vuln:dos

**Target:** ActiveRecord PostgreSQL Money OID type coercion
**Root cause:** Regex `^-?\D*[\d,]+\.\d{2}$` has overlapping quantifiers where `,` matches both `\D*` and `[\d,]+`, producing O(n^2) backtracking on long comma strings.
**Steps:**
1. Install pg gem, `rails new moneydos --database=postgresql`, `rails db:setup`
2. `rails g scaffold Money amount:money` then `rake db:migrate`
3. In console: `app.host='localhost'; app.get '/money'; token=app.session[:_csrf_token]`
4. POST `params: {money: {amount: ("$" + ","*100000 + ".11!")}, authenticity_token: token}`
5. Observe ~40s CPU spin; increase comma count to saturate host
**How found:** Code reading of the Money type regex; noticed `,` can match both `\D*` and `[\d,]+`, hypothesizing quadratic backtracking, then confirmed with crafted input.
**Exploitation:** Attacker submits a POST body with a money amount containing a long run of commas prefixed by `$` and suffixed with `.11!`, triggering catastrophic backtracking in the Money type cast during save; repeated requests saturate CPU.
**Insight:** When auditing regexes, look for characters that can be matched by two adjacent quantifiers (e.g. `,` in both `\D*` and `[\d,]+`) — that overlap is the ReDoS signature, and type-coercion code paths reachable from request params are prime targets.

