HSEC-2026-0011

Superlinear encoding of numbers with large coefficients

Encoding (pretty-printing) a Scientific number whose coefficient has many digits took time quadratic in the number of digits: the decimal digits were extracted by repeatedly dividing the whole coefficient by 10, once per digit. The Show instance, Data.Text.Lazy.Builder.Scientific and Data.ByteString.Builder.Scientific — which aeson uses to encode JSON numbers — all share this code path. A number with one million digits took about a minute to show, and about a tenth of a second after the fix.

This is a denial-of-service risk for applications that decode numbers from an untrusted source and encode them again, e.g. JSON proxies, loggers or API gateways built on aeson.

Resolution

scientific-0.3.9.0 reimplemented normalize and toDecimalDigits (the digit-extraction primitive) to be practically linear in the coefficient size.

Note that scientific-0.3.9.0 introduced a regression of its own; see HSEC-2026-0012. Upgrade directly to scientific-0.3.10.0 or later, which fixes both issues.

Credits

Reported by Andrzej Rybczak (@arybczak); fixed by Oleg Grenrus (@phadej).

Info

Published
November 03, 2026
Modified
November 03, 2026
CAPECs
< none >
CWEs
407
Keywords
dos, json, encoding
Aliases
< none >
Related
HSEC-2026-0012
References
[REPORT] https://github.com/basvandijk/scientific/pull/109
[FIX] https://github.com/basvandijk/scientific/pull/116
[FIX] https://github.com/basvandijk/scientific/pull/117
[DISCUSSION] https://www.reddit.com/r/haskell/comments/1xbj59g/dont_use_scientific_for_calculations_it_can/

Affected

@hackage/scientific
CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Versions
>=0 && <0.3.9.0
Declarations
< none >
Affected APIs
< none >