{"id":"GHSA-rhv4-8758-jx7v","summary":"Decimal: Unbounded exponent in `Decimal.new` 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.","aliases":["CVE-2026-32686","EEF-CVE-2026-32686"],"modified":"2026-08-05T12:45:47.358985491Z","published":"2026-05-12T15:09:20Z","database_specific":{"github_reviewed_at":"2026-05-12T15:09:20Z","nvd_published_at":"2026-05-07T15:16:05Z","cwe_ids":["CWE-400"],"severity":"MODERATE","github_reviewed":true},"references":[{"type":"WEB","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":"WEB","url":"https://github.com/ericmj/decimal/commit/6a523f3a73b8c9974540e21c7aa88f1258bb35ae"},{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2026-32686.html"},{"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"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2026-32686"}],"affected":[{"package":{"name":"decimal","ecosystem":"Hex","purl":"pkg:hex/decimal"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0.1.0"},{"fixed":"3.0.0"}]}],"versions":["0.1.1","0.1.2","0.2.0","0.2.1","0.2.2","0.2.3","0.2.4","0.2.5","1.0.0","1.0.1","1.1.0","1.1.1","1.1.2","1.2.0","1.3.0","1.3.1","1.4.0","1.4.1","1.5.0","1.6.0","1.7.0","1.8.0","1.8.1","1.9.0","1.9.0-rc.0","2.0.0","2.0.0-rc.0","2.1.0","2.1.1","2.2.0","2.3.0","2.4.0","2.4.1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-rhv4-8758-jx7v/GHSA-rhv4-8758-jx7v.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"}]}