hsec-2026-0011

osv_haskell
Description

# 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).

Timeline
Published
unknown
Last Modified
unknown
CVSS Details

CVSS details not available.

Affected Products

No product information available.

References
Linked Vulnerabilities

No linked vulnerabilities found.

{
  "affected": [
    {
      "database_specific": {
        "human_link": "https://github.com/haskell/security-advisories/tree/main/advisories/published/2026/HSEC-2026-0011.md",
        "osv": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export/2026/HSEC-2026-0011.json",
        "source": "https://github.com/haskell/security-advisories/blob/generated/osv-export/2026/HSEC-2026-0011.json"
      },
      "package": {
        "ecosystem": "Hackage",
        "name": "scientific",
        "purl": "pkg:hackage/scientific"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.3.9.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "severity": [
        {
          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
          "type": "CVSS_V3"
        }
      ],
      "versions": [
        "0.0.0.0",
        "0.0.0.1",
        "0.0.0.2",
        "0.1.0.0",
        "0.1.0.1",
        "0.2.0.0",
        "0.2.0.1",
        "0.2.0.2",
        "0.3.0.0",
        "0.3.0.1",
        "0.3.0.2",
        "0.3.1.0",
        "0.3.2.0",
        "0.3.2.1",
        "0.3.2.2",
        "0.3.3.0",
        "0.3.3.1",
        "0.3.3.2",
        "0.3.3.3",
        "0.3.3.4",
        "0.3.3.5",
        "0.3.3.6",
        "0.3.3.7",
        "0.3.3.8",
        "0.3.4.0",
        "0.3.4.1",
        "0.3.4.10",
        "0.3.4.11",
        "0.3.4.12",
        "0.3.4.13",
        "0.3.4.14",
        "0.3.4.15",
        "0.3.4.2",
        "0.3.4.3",
        "0.3.4.4",
        "0.3.4.5",
        "0.3.4.6",
        "0.3.4.7",
        "0.3.4.8",
        "0.3.4.9",
        "0.3.5.0",
        "0.3.5.1",
        "0.3.5.2",
        "0.3.5.3",
        "0.3.6.0",
        "0.3.6.1",
        "0.3.6.2",
        "0.3.7.0",
        "0.3.8.0",
        "0.3.8.1"
      ]
    }
  ],
  "database_specific": {
    "home": "https://github.com/haskell/security-advisories",
    "osvs": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export",
    "repository": "https://github.com/haskell/security-advisories"
  },
  "details": "# Superlinear encoding of numbers with large coefficients\n\nEncoding (pretty-printing) a `Scientific` number whose coefficient has many\ndigits took time quadratic in the number of digits: the decimal digits were\nextracted by repeatedly dividing the whole coefficient by 10, once per digit.\nThe `Show` instance, `Data.Text.Lazy.Builder.Scientific` and\n`Data.ByteString.Builder.Scientific` — which `aeson` uses to encode JSON\nnumbers — all share this code path. A number with one million digits took\nabout a minute to show, and about a tenth of a second after the fix.\n\nThis is a denial-of-service risk for applications that decode numbers from an\nuntrusted source and encode them again, e.g. JSON proxies, loggers or API\ngateways built on `aeson`.\n\n## Resolution\n\n`scientific-0.3.9.0` reimplemented `normalize` and `toDecimalDigits` (the\ndigit-extraction primitive) to be practically linear in the coefficient size.\n\nNote that `scientific-0.3.9.0` introduced a regression of its own; see\nHSEC-2026-0012. Upgrade\ndirectly to `scientific-0.3.10.0` or later, which fixes both issues.\n\n## Credits\n\nReported by Andrzej Rybczak (@arybczak); fixed by Oleg Grenrus (@phadej).\n",
  "id": "HSEC-2026-0011",
  "modified": "2026-11-03T22:45:02.729867511Z",
  "published": "2026-11-03T22:32:58Z",
  "references": [
    {
      "type": "REPORT",
      "url": "https://github.com/basvandijk/scientific/pull/109"
    },
    {
      "type": "FIX",
      "url": "https://github.com/basvandijk/scientific/pull/116"
    },
    {
      "type": "FIX",
      "url": "https://github.com/basvandijk/scientific/pull/117"
    },
    {
      "type": "DISCUSSION",
      "url": "https://www.reddit.com/r/haskell/comments/1xbj59g/dont_use_scientific_for_calculations_it_can/"
    }
  ],
  "related": [
    "HSEC-2026-0012"
  ],
  "schema_version": "1.9.2",
  "summary": "Superlinear encoding of numbers with large coefficients"
}
View JSON API Download JSON