{"id":"CVE-2026-32686","aliases":["EEF-CVE-2026-32686","GHSA-rhv4-8758-jx7v"],"url":"https://o3.security/vulnerability/CVE-2026-32686","summary":"Unbounded exponent in decimal enables unauthenticated DoS","details":"Summary\n`decimal` doesn't bound the exponent on parsed input, so something like `\"1e10000000\"` is parsed fine but then explodes the memory to more than 7GB if you run e.g. `Decimal.add(Decimal.parse(\"1e10000000\"), 1)` because for positive `exp`, the function tail-recurses with `coef * 10` and `exp - 1` per iteration, growing the bignum coefficient by one digit each step. In the worst case, one request is enough to OOM the BEAM.\n\n### Details\n`Decimal.new/parse/cast` happily store huge exponents. After that, a bunch of core paths allocate proportional to `exp`:\n- `add/sub/div` go through `add_align`, which calls `pow10(exp1 - exp2)` and builds a giant bignum (lib/decimal.ex:1734-1738, 1827).\n- `to_string/2` with `:normal` (also `:xsd` and the `String.Chars` impl) does `:lists.duplicate(exp, ?0)` (lib/decimal.ex:1506, 1513).\n- `to_integer/1` recurses `coef * 10`, `exp - 1` once per unit of `exp` (lib/decimal.ex:1603-1605).\n- `round/3` does the same `:lists.duplicate` trick on the exp difference (lib/decimal.ex:1850, 1874).\n- `compare/3` with a threshold argument loops back into `add`/`sub`, so it's vulnerable too (lib/decimal.ex:331-332).\n\n### PoC\nAny of these will hang or OOM the BEAM:\n```elixir\nDecimal.add(Decimal.new(\"1\"), Decimal.new(\"1e1000000000\"))\nDecimal.to_string(Decimal.new(\"1e1000000000\"), :normal)\nDecimal.to_integer(Decimal.new(\"1e1000000000\"))\nDecimal.round(Decimal.new(\"1e1000000000\"))\n```\n\n### Impact\nUnauthenticated remote DoS. Anything that takes a user-supplied decimal (JSON, form field, Ecto `:decimal` field — basically everywhere) and then does arithmetic, rounding, `to_integer`, or `to_string` on it is exposed. One request can kill the node with a Out-of-Memory exception.\n\n### Note on the security fixes done in version 2.4.0\nWhile `2.4.0` has the changes to mitigate this issue it's not considered as a patched version because it doesn't have them enabled by default.","published":"2026-05-07T14:04:47.222Z","modified":"2026-09-10T03:46:14.395168633Z","cvss":null,"epss":{"score":0.00321,"percentile":0.24292,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Hex","name":"decimal","fixedVersion":"3.0.0"}],"fix":{"url":"https://github.com/ericmj/decimal/commit/6a523f3a73b8c9974540e21c7aa88f1258bb35ae","label":"ericmj/decimal@6a523f3"},"references":[{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2026-32686.html"},{"type":"WEB","url":"https://github.com"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2026-32686"},{"type":"WEB","url":"https://repo.hex.pm"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/32xxx/CVE-2026-32686.json"},{"type":"ADVISORY","url":"https://github.com/ericmj/decimal/security/advisories/GHSA-rhv4-8758-jx7v"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-32686"},{"type":"FIX","url":"https://github.com/ericmj/decimal/commit/6a523f3a73b8c9974540e21c7aa88f1258bb35ae"},{"type":"FIX","url":"https://github.com/ericmj/decimal/commit/bc11f4a2b6fb61fc1360a0ab4e79141bba918841"},{"type":"PACKAGE","url":"https://github.com/ericmj/decimal"},{"type":"WEB","url":"https://github.com/ericmj/decimal/releases/tag/v2.4.0"},{"type":"WEB","url":"https://github.com/ericmj/decimal/releases/tag/v3.0.0"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-09-10T03:46:14.395168633Z"}}