CVE-2026-115274 (GCVE-0-2026-115274)
Vulnerability from cvelistv5 – Published: 2026-10-30 08:57 – Updated: 2026-10-30 16:51
VLAI
EPSS
VEX
Title
Unbounded integer parsing in JSON.decode/1 enables CPU and memory exhaustion denial of service in Elixir
Summary
Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library's JSON module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.
JSON.decode/1 and JSON.decode!/1 convert each integer literal with erlang:binary_to_integer/1 and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises SystemLimitError. Applications generated by phx.new decode request bodies with JSON in Plug.Parsers, before routing and authentication.
This issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5.
Severity
SSVC
Exploitation: poc
Automatable: yes
Technical Impact: partial
CISA Coordinator · CISA-ADP (v2.0.3)
Decision recorded 2026-10-30 16:51 UTC
CWE
- CWE-1284 - Improper Validation of Specified Quantity in Input
Assigner
References
8 references
Impacted products
2 products
| Vendor | Product | Version | CPE status | |
|---|---|---|---|---|
| elixir-lang | elixir |
Affected:
1.18.0-rc.0 , < 1.18.6
(semver)
Affected: 1.19.0-rc.0 , < 1.19.7 (semver) Affected: 1.20.0-rc.0 , < 1.20.5 (semver) cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:* |
||
| elixir-lang | elixir |
Affected:
793c1147210388587defb649f25f293ffbfa6b1b , < *
(git)
cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:* |
Date Public
2026-10-30 08:57
{
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-115274",
"options": [
{
"Exploitation": "poc"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-30T16:51:17.679403Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-30T16:51:45.396Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"references": [
{
"tags": [
"exploit"
],
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
}
],
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir",
"packageURL": "pkg:otp/elixir?repository_url=https:%2F%2Fgithub.com%2Felixir-lang%2Felixir\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Felixir-lang%2Felixir.git",
"product": "elixir",
"programFiles": [
"lib/json.ex",
"src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"lessThan": "1.18.6",
"status": "affected",
"version": "1.18.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.19.7",
"status": "affected",
"version": "1.19.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.20.5",
"status": "affected",
"version": "1.20.0-rc.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir-lang/elixir",
"packageURL": "pkg:github/elixir-lang/elixir",
"product": "elixir",
"programFiles": [
"lib/elixir/lib/json.ex",
"lib/elixir/src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"changes": [
{
"at": "c81f12265919c34a0d5134f1905a4eb4edaea1c2",
"status": "unaffected"
},
{
"at": "7154e8781da9fd016a973ea01776a011c8b5726a",
"status": "unaffected"
},
{
"at": "cd158efacdc10b30232864251747dff9b8387dfe",
"status": "unaffected"
},
{
"at": "ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396",
"status": "unaffected"
}
],
"lessThan": "*",
"status": "affected",
"version": "793c1147210388587defb649f25f293ffbfa6b1b",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.18.6",
"versionStartIncluding": "1.18.0-rc.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.19.7",
"versionStartIncluding": "1.19.0-rc.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.20.5",
"versionStartIncluding": "1.20.0-rc.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "David Vieira Kurz"
},
{
"lang": "en",
"type": "finder",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "reporter",
"value": "David Vieira Kurz"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Jos\u00e9 Valim"
},
{
"lang": "en",
"type": "coordinator",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-25T12:21:17.000Z",
"datePublic": "2026-10-30T08:57:17.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eImproper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s \u003ccode\u003eJSON\u003c/code\u003e module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eJSON.decode/1\u003c/code\u003e and \u003ccode\u003eJSON.decode!/1\u003c/code\u003e convert each integer literal with \u003ccode\u003eerlang:binary_to_integer/1\u003c/code\u003e and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises \u003ccode\u003eSystemLimitError\u003c/code\u003e. Applications generated by \u003ccode\u003ephx.new\u003c/code\u003e decode request bodies with \u003ccode\u003eJSON\u003c/code\u003e in \u003ccode\u003ePlug.Parsers\u003c/code\u003e, before routing and authentication.\u003c/p\u003e\n\u003cp\u003eThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s `JSON` module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\n\n`JSON.decode/1` and `JSON.decode!/1` convert each integer literal with `erlang:binary_to_integer/1` and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises `SystemLimitError`. Applications generated by `phx.new` decode request bodies with `JSON` in `Plug.Parsers`, before routing and authentication.\n\nThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5."
}
],
"value": "Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s JSON module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\n\nJSON.decode/1 and JSON.decode!/1 convert each integer literal with erlang:binary_to_integer/1 and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises SystemLimitError. Applications generated by phx.new decode request bodies with JSON in Plug.Parsers, before routing and authentication.\n\nThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAn unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with \u003ccode\u003eJSON\u003c/code\u003e, including new Phoenix applications by default.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "An unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with `JSON`, including new Phoenix applications by default."
}
],
"value": "An unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with JSON, including new Phoenix applications by default."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "LOW",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-1284",
"description": "CWE-1284 Improper Validation of Specified Quantity in Input",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-30T09:01:54.926Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "Unbounded integer parsing in JSON.decode/1 enables CPU and memory exhaustion denial of service in Elixir",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
},
{
"name": "EEF CNA record for CVE-2026-115274",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-115274.html"
},
{
"name": "OSV record EEF-CVE-2026-115274",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-115274"
},
{
"name": "Introducing commit 793c114 in elixir-lang/elixir",
"tags": [
"related"
],
"url": "https://github.com/elixir-lang/elixir/commit/793c1147210388587defb649f25f293ffbfa6b1b"
},
{
"name": "Fix commit c81f122 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/c81f12265919c34a0d5134f1905a4eb4edaea1c2"
},
{
"name": "Fix commit 7154e87 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/7154e8781da9fd016a973ea01776a011c8b5726a"
},
{
"name": "Fix commit cd158ef in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/cd158efacdc10b30232864251747dff9b8387dfe"
},
{
"name": "Fix commit ee5cc23 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Unbounded integer parsing in JSON.decode/1 enables CPU and memory exhaustion denial of service in Elixir",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eDecode untrusted JSON with an \u003ccode\u003einteger\u003c/code\u003e decoder that rejects long digit runs before conversion:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-elixir\"\u003edefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026amp;safe_integer/1) do\n {decoded, :ok, \"\"} -\u0026gt; decoded\n _ -\u0026gt; raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u0026lt;= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn Phoenix, pass \u003ccode\u003eSafeJSON\u003c/code\u003e to \u003ccode\u003ePlug.Parsers\u003c/code\u003e as \u003ccode\u003ejson_decoder\u003c/code\u003e instead of \u003ccode\u003ePhoenix.json_library()\u003c/code\u003e.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Decode untrusted JSON with an `integer` decoder that rejects long digit runs before conversion:\n\n```elixir\ndefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026safe_integer/1) do\n {decoded, :ok, \"\"} -\u003e decoded\n _ -\u003e raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u003c= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n```\n\nIn Phoenix, pass `SafeJSON` to `Plug.Parsers` as `json_decoder` instead of `Phoenix.json_library()`."
}
],
"value": "Decode untrusted JSON with an integer decoder that rejects long digit runs before conversion:\n\ndefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026safe_integer/1) do\n {decoded, :ok, \"\"} -\u003e decoded\n _ -\u003e raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u003c= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n\nIn Phoenix, pass SafeJSON to Plug.Parsers as json_decoder instead of Phoenix.json_library()."
}
],
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eBuild \u003ccode\u003ebody = \"[\" \u0026lt;\u0026gt; Enum.map_join(1..7, \",\", fn _ -\u0026gt; String.duplicate(\"9\", 1_000_000) end) \u0026lt;\u0026gt; \"]\"\u003c/code\u003e, a body of about 7 MB.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(body)\u003c/code\u003e returns \u003ccode\u003e{:ok, ...}\u003c/code\u003e after about one second of CPU.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(String.duplicate(\"9\", 1_000_000))\u003c/code\u003e takes 100 to 300 times as long as \u003ccode\u003eJSON.decode(\"\\\"\" \u0026lt;\u0026gt; String.duplicate(\"9\", 1_000_000) \u0026lt;\u0026gt; \"\\\"\")\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(String.duplicate(\"9\", 1_400_000))\u003c/code\u003e raises \u003ccode\u003eSystemLimitError\u003c/code\u003e.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Build `body = \"[\" \u003c\u003e Enum.map_join(1..7, \",\", fn _ -\u003e String.duplicate(\"9\", 1_000_000) end) \u003c\u003e \"]\"`, a body of about 7 MB.\n2. `JSON.decode(body)` returns `{:ok, ...}` after about one second of CPU.\n3. `JSON.decode(String.duplicate(\"9\", 1_000_000))` takes 100 to 300 times as long as `JSON.decode(\"\\\"\" \u003c\u003e String.duplicate(\"9\", 1_000_000) \u003c\u003e \"\\\"\")`.\n4. `JSON.decode(String.duplicate(\"9\", 1_400_000))` raises `SystemLimitError`."
}
],
"value": "* Build body = \"[\" \u003c\u003e Enum.map_join(1..7, \",\", fn _ -\u003e String.duplicate(\"9\", 1_000_000) end) \u003c\u003e \"]\", a body of about 7 MB.\n* JSON.decode(body) returns {:ok, ...} after about one second of CPU.\n* JSON.decode(String.duplicate(\"9\", 1_000_000)) takes 100 to 300 times as long as JSON.decode(\"\\\"\" \u003c\u003e String.duplicate(\"9\", 1_000_000) \u003c\u003e \"\\\"\").\n* JSON.decode(String.duplicate(\"9\", 1_400_000)) raises SystemLimitError."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Default integer decoder\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eJSON.decode/1\u003c/code\u003e and \u003ccode\u003eJSON.decode!/1\u003c/code\u003e call \u003ccode\u003eJSON.decode/3\u003c/code\u003e without an \u003ccode\u003einteger\u003c/code\u003e decoder. Up to the removal of Erlang/OTP 26 support, \u003ccode\u003eJSON.decode/3\u003c/code\u003e used the vendored \u003ccode\u003eelixir_json\u003c/code\u003e module, whose default is \u003ccode\u003efun erlang:binary_to_integer/1\u003c/code\u003e. It now calls OTP\u0027s \u003ccode\u003e:json.decode/3\u003c/code\u003e, which has the same default. The \u003ccode\u003eJSON.decode/3\u003c/code\u003e documentation names \u003ccode\u003e\u0026amp;String.to_integer/1\u003c/code\u003e as the default, which converts the same way.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Unbounded conversion\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises \u003ccode\u003eSystemLimitError\u003c/code\u003e, which \u003ccode\u003eJSON.decode/3\u003c/code\u003e does not catch.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Reach\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ephx.new\u003c/code\u003e sets \u003ccode\u003econfig :phoenix, :json_library, JSON\u003c/code\u003e, and the generated endpoint passes \u003ccode\u003ePhoenix.json_library()\u003c/code\u003e to \u003ccode\u003ePlug.Parsers\u003c/code\u003e as \u003ccode\u003ejson_decoder\u003c/code\u003e. \u003ccode\u003ePlug.Parsers\u003c/code\u003e runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the \u003ccode\u003eSystemLimitError\u003c/code\u003e into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its \u003ccode\u003edecoding_integer_digit_limit\u003c/code\u003e (1024 by default) before conversion.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Default integer decoder**\n\n`JSON.decode/1` and `JSON.decode!/1` call `JSON.decode/3` without an `integer` decoder. Up to the removal of Erlang/OTP 26 support, `JSON.decode/3` used the vendored `elixir_json` module, whose default is `fun erlang:binary_to_integer/1`. It now calls OTP\u0027s `:json.decode/3`, which has the same default. The `JSON.decode/3` documentation names `\u0026String.to_integer/1` as the default, which converts the same way.\n\n**2. Unbounded conversion**\n\nThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises `SystemLimitError`, which `JSON.decode/3` does not catch.\n\n**3. Reach**\n\n`phx.new` sets `config :phoenix, :json_library, JSON`, and the generated endpoint passes `Phoenix.json_library()` to `Plug.Parsers` as `json_decoder`. `Plug.Parsers` runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the `SystemLimitError` into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its `decoding_integer_digit_limit` (1024 by default) before conversion."
}
],
"value": "1. Default integer decoder\n\nJSON.decode/1 and JSON.decode!/1 call JSON.decode/3 without an integer decoder. Up to the removal of Erlang/OTP 26 support, JSON.decode/3 used the vendored elixir_json module, whose default is fun erlang:binary_to_integer/1. It now calls OTP\u0027s :json.decode/3, which has the same default. The JSON.decode/3 documentation names \u0026String.to_integer/1 as the default, which converts the same way.\n\n2. Unbounded conversion\n\nThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises SystemLimitError, which JSON.decode/3 does not catch.\n\n3. Reach\n\nphx.new sets config :phoenix, :json_library, JSON, and the generated endpoint passes Phoenix.json_library() to Plug.Parsers as json_decoder. Plug.Parsers runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the SystemLimitError into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its decoding_integer_digit_limit (1024 by default) before conversion."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-115274",
"datePublished": "2026-10-30T08:57:16.847Z",
"dateReserved": "2026-10-23T12:45:01.103Z",
"dateUpdated": "2026-10-30T16:51:45.396Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"epss": {
"cve": "CVE-2026-115274",
"date": "2026-10-30",
"epss": "0.00498",
"percentile": "0.42697"
},
"nvd": {
"cve": {
"affected": [
{
"affectedData": [
{
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir",
"packageURL": "pkg:otp/elixir?repository_url=https:%2F%2Fgithub.com%2Felixir-lang%2Felixir\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Felixir-lang%2Felixir.git",
"product": "elixir",
"programFiles": [
"lib/json.ex",
"src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"lessThan": "1.18.6",
"status": "affected",
"version": "1.18.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.19.7",
"status": "affected",
"version": "1.19.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.20.5",
"status": "affected",
"version": "1.20.0-rc.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir-lang/elixir",
"packageURL": "pkg:github/elixir-lang/elixir",
"product": "elixir",
"programFiles": [
"lib/elixir/lib/json.ex",
"lib/elixir/src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"changes": [
{
"at": "c81f12265919c34a0d5134f1905a4eb4edaea1c2",
"status": "unaffected"
},
{
"at": "7154e8781da9fd016a973ea01776a011c8b5726a",
"status": "unaffected"
},
{
"at": "cd158efacdc10b30232864251747dff9b8387dfe",
"status": "unaffected"
},
{
"at": "ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396",
"status": "unaffected"
}
],
"lessThan": "*",
"status": "affected",
"version": "793c1147210388587defb649f25f293ffbfa6b1b",
"versionType": "git"
}
]
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s JSON module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\n\nJSON.decode/1 and JSON.decode!/1 convert each integer literal with erlang:binary_to_integer/1 and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises SystemLimitError. Applications generated by phx.new decode request bodies with JSON in Plug.Parsers, before routing and authentication.\n\nThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5."
}
],
"id": "CVE-2026-115274",
"lastModified": "2026-10-30T19:39:14.897",
"metrics": {
"cvssMetricV40": [
{
"cvssData": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"availabilityRequirement": "NOT_DEFINED",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"confidentialityRequirement": "NOT_DEFINED",
"exploitMaturity": "NOT_DEFINED",
"integrityRequirement": "NOT_DEFINED",
"modifiedAttackComplexity": "NOT_DEFINED",
"modifiedAttackRequirements": "NOT_DEFINED",
"modifiedAttackVector": "NOT_DEFINED",
"modifiedPrivilegesRequired": "NOT_DEFINED",
"modifiedSubAvailabilityImpact": "NOT_DEFINED",
"modifiedSubConfidentialityImpact": "NOT_DEFINED",
"modifiedSubIntegrityImpact": "NOT_DEFINED",
"modifiedUserInteraction": "NOT_DEFINED",
"modifiedVulnAvailabilityImpact": "NOT_DEFINED",
"modifiedVulnConfidentialityImpact": "NOT_DEFINED",
"modifiedVulnIntegrityImpact": "NOT_DEFINED",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"version": "4.0",
"vulnAvailabilityImpact": "LOW",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"type": "Secondary"
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"id": "CVE-2026-115274",
"options": [
{
"exploitation": "poc"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-30T16:51:17.679403Z",
"version": "2.0.3"
}
}
]
},
"published": "2026-10-30T09:17:14.103",
"references": [
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://cna.erlef.org/cves/CVE-2026-115274.html"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/commit/7154e8781da9fd016a973ea01776a011c8b5726a"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/commit/793c1147210388587defb649f25f293ffbfa6b1b"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/commit/c81f12265919c34a0d5134f1905a4eb4edaea1c2"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/commit/cd158efacdc10b30232864251747dff9b8387dfe"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/commit/ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
},
{
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-115274"
},
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
}
],
"sourceIdentifier": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"vulnStatus": "Deferred",
"weaknesses": [
{
"description": [
{
"lang": "en",
"value": "CWE-1284"
}
],
"source": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"type": "Secondary"
}
]
}
},
"vulnrichment": {
"containers": {
"adp": [
{
"metrics": [
{
"other": {
"content": {
"id": "CVE-2026-115274",
"options": [
{
"Exploitation": "poc"
},
{
"Automatable": "yes"
},
{
"Technical Impact": "partial"
}
],
"role": "CISA Coordinator",
"timestamp": "2026-10-30T16:51:17.679403Z",
"version": "2.0.3"
},
"type": "ssvc"
}
}
],
"providerMetadata": {
"dateUpdated": "2026-10-30T16:51:40.079Z",
"orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"shortName": "CISA-ADP"
},
"references": [
{
"tags": [
"exploit"
],
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
}
],
"title": "CISA ADP Vulnrichment"
}
],
"cna": {
"affected": [
{
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir",
"packageURL": "pkg:otp/elixir?repository_url=https:%2F%2Fgithub.com%2Felixir-lang%2Felixir\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Felixir-lang%2Felixir.git",
"product": "elixir",
"programFiles": [
"lib/json.ex",
"src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"lessThan": "1.18.6",
"status": "affected",
"version": "1.18.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.19.7",
"status": "affected",
"version": "1.19.0-rc.0",
"versionType": "semver"
},
{
"lessThan": "1.20.5",
"status": "affected",
"version": "1.20.0-rc.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"\u0027Elixir.JSON\u0027",
"elixir_json"
],
"packageName": "elixir-lang/elixir",
"packageURL": "pkg:github/elixir-lang/elixir",
"product": "elixir",
"programFiles": [
"lib/elixir/lib/json.ex",
"lib/elixir/src/elixir_json.erl"
],
"programRoutines": [
{
"name": "\u0027Elixir.JSON\u0027:decode/1"
},
{
"name": "\u0027Elixir.JSON\u0027:\u0027decode!\u0027/1"
},
{
"name": "\u0027Elixir.JSON\u0027:decode/3"
},
{
"name": "elixir_json:decode/3"
}
],
"repo": "https://github.com/elixir-lang/elixir",
"vendor": "elixir-lang",
"versions": [
{
"changes": [
{
"at": "c81f12265919c34a0d5134f1905a4eb4edaea1c2",
"status": "unaffected"
},
{
"at": "7154e8781da9fd016a973ea01776a011c8b5726a",
"status": "unaffected"
},
{
"at": "cd158efacdc10b30232864251747dff9b8387dfe",
"status": "unaffected"
},
{
"at": "ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396",
"status": "unaffected"
}
],
"lessThan": "*",
"status": "affected",
"version": "793c1147210388587defb649f25f293ffbfa6b1b",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.18.6",
"versionStartIncluding": "1.18.0-rc.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.19.7",
"versionStartIncluding": "1.19.0-rc.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:a:elixir-lang:elixir:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.20.5",
"versionStartIncluding": "1.20.0-rc.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "David Vieira Kurz"
},
{
"lang": "en",
"type": "finder",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "reporter",
"value": "David Vieira Kurz"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Jos\u00e9 Valim"
},
{
"lang": "en",
"type": "coordinator",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"dateAssigned": "2026-10-25T12:21:17.000Z",
"datePublic": "2026-10-30T08:57:17.000Z",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eImproper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s \u003ccode\u003eJSON\u003c/code\u003e module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eJSON.decode/1\u003c/code\u003e and \u003ccode\u003eJSON.decode!/1\u003c/code\u003e convert each integer literal with \u003ccode\u003eerlang:binary_to_integer/1\u003c/code\u003e and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises \u003ccode\u003eSystemLimitError\u003c/code\u003e. Applications generated by \u003ccode\u003ephx.new\u003c/code\u003e decode request bodies with \u003ccode\u003eJSON\u003c/code\u003e in \u003ccode\u003ePlug.Parsers\u003c/code\u003e, before routing and authentication.\u003c/p\u003e\n\u003cp\u003eThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s `JSON` module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\n\n`JSON.decode/1` and `JSON.decode!/1` convert each integer literal with `erlang:binary_to_integer/1` and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises `SystemLimitError`. Applications generated by `phx.new` decode request bodies with `JSON` in `Plug.Parsers`, before routing and authentication.\n\nThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5."
}
],
"value": "Improper Validation of Specified Quantity in Input vulnerability in the Elixir standard library\u0027s JSON module allows an unauthenticated attacker who supplies a JSON document to cause a denial of service through CPU and memory exhaustion.\n\nJSON.decode/1 and JSON.decode!/1 convert each integer literal with erlang:binary_to_integer/1 and do not bound its length. A literal of one million digits decodes successfully but costs 100 to 300 times as much CPU as a string of the same length, so one request body of a few megabytes holds a scheduler for about a second. A literal of more than about 1.29 million digits raises SystemLimitError. Applications generated by phx.new decode request bodies with JSON in Plug.Parsers, before routing and authentication.\n\nThis issue affects elixir: from 1.18.0-rc.0 before 1.18.6, from 1.19.0-rc.0 before 1.19.7, and from 1.20.0-rc.0 before 1.20.5."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eAn unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with \u003ccode\u003eJSON\u003c/code\u003e, including new Phoenix applications by default.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "An unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with `JSON`, including new Phoenix applications by default."
}
],
"value": "An unauthenticated client that sends a JSON body with integer literals of about a million digits makes the server spend about a second of CPU per request and allocate large bignums. Sustained requests exhaust CPU on applications that decode untrusted JSON with JSON, including new Phoenix applications by default."
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "LOW",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-1284",
"description": "CWE-1284 Improper Validation of Specified Quantity in Input",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-30T09:01:54.926Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"name": "Unbounded integer parsing in JSON.decode/1 enables CPU and memory exhaustion denial of service in Elixir",
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/elixir-lang/elixir/security/advisories/GHSA-rp5q-xqhq-926h"
},
{
"name": "EEF CNA record for CVE-2026-115274",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-115274.html"
},
{
"name": "OSV record EEF-CVE-2026-115274",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-115274"
},
{
"name": "Introducing commit 793c114 in elixir-lang/elixir",
"tags": [
"related"
],
"url": "https://github.com/elixir-lang/elixir/commit/793c1147210388587defb649f25f293ffbfa6b1b"
},
{
"name": "Fix commit c81f122 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/c81f12265919c34a0d5134f1905a4eb4edaea1c2"
},
{
"name": "Fix commit 7154e87 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/7154e8781da9fd016a973ea01776a011c8b5726a"
},
{
"name": "Fix commit cd158ef in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/cd158efacdc10b30232864251747dff9b8387dfe"
},
{
"name": "Fix commit ee5cc23 in elixir-lang/elixir",
"tags": [
"patch"
],
"url": "https://github.com/elixir-lang/elixir/commit/ee5cc23f8928aa5a0f25bb7f28e42ecfc7b7d396"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Unbounded integer parsing in JSON.decode/1 enables CPU and memory exhaustion denial of service in Elixir",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eDecode untrusted JSON with an \u003ccode\u003einteger\u003c/code\u003e decoder that rejects long digit runs before conversion:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-elixir\"\u003edefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026amp;safe_integer/1) do\n {decoded, :ok, \"\"} -\u0026gt; decoded\n _ -\u0026gt; raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u0026lt;= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIn Phoenix, pass \u003ccode\u003eSafeJSON\u003c/code\u003e to \u003ccode\u003ePlug.Parsers\u003c/code\u003e as \u003ccode\u003ejson_decoder\u003c/code\u003e instead of \u003ccode\u003ePhoenix.json_library()\u003c/code\u003e.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Decode untrusted JSON with an `integer` decoder that rejects long digit runs before conversion:\n\n```elixir\ndefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026safe_integer/1) do\n {decoded, :ok, \"\"} -\u003e decoded\n _ -\u003e raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u003c= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n```\n\nIn Phoenix, pass `SafeJSON` to `Plug.Parsers` as `json_decoder` instead of `Phoenix.json_library()`."
}
],
"value": "Decode untrusted JSON with an integer decoder that rejects long digit runs before conversion:\n\ndefmodule SafeJSON do\n def decode!(binary) do\n case JSON.decode(binary, :ok, integer: \u0026safe_integer/1) do\n {decoded, :ok, \"\"} -\u003e decoded\n _ -\u003e raise ArgumentError, \"invalid JSON\"\n end\n end\n\n defp safe_integer(digits) when byte_size(digits) \u003c= 1024, do: String.to_integer(digits)\n defp safe_integer(_digits), do: raise(ArgumentError, \"integer too long\")\nend\n\nIn Phoenix, pass SafeJSON to Plug.Parsers as json_decoder instead of Phoenix.json_library()."
}
],
"x_proofOfConcept": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003col\u003e\n\u003cli\u003eBuild \u003ccode\u003ebody = \"[\" \u0026lt;\u0026gt; Enum.map_join(1..7, \",\", fn _ -\u0026gt; String.duplicate(\"9\", 1_000_000) end) \u0026lt;\u0026gt; \"]\"\u003c/code\u003e, a body of about 7 MB.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(body)\u003c/code\u003e returns \u003ccode\u003e{:ok, ...}\u003c/code\u003e after about one second of CPU.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(String.duplicate(\"9\", 1_000_000))\u003c/code\u003e takes 100 to 300 times as long as \u003ccode\u003eJSON.decode(\"\\\"\" \u0026lt;\u0026gt; String.duplicate(\"9\", 1_000_000) \u0026lt;\u0026gt; \"\\\"\")\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eJSON.decode(String.duplicate(\"9\", 1_400_000))\u003c/code\u003e raises \u003ccode\u003eSystemLimitError\u003c/code\u003e.\u003c/li\u003e\n\u003c/ol\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "1. Build `body = \"[\" \u003c\u003e Enum.map_join(1..7, \",\", fn _ -\u003e String.duplicate(\"9\", 1_000_000) end) \u003c\u003e \"]\"`, a body of about 7 MB.\n2. `JSON.decode(body)` returns `{:ok, ...}` after about one second of CPU.\n3. `JSON.decode(String.duplicate(\"9\", 1_000_000))` takes 100 to 300 times as long as `JSON.decode(\"\\\"\" \u003c\u003e String.duplicate(\"9\", 1_000_000) \u003c\u003e \"\\\"\")`.\n4. `JSON.decode(String.duplicate(\"9\", 1_400_000))` raises `SystemLimitError`."
}
],
"value": "* Build body = \"[\" \u003c\u003e Enum.map_join(1..7, \",\", fn _ -\u003e String.duplicate(\"9\", 1_000_000) end) \u003c\u003e \"]\", a body of about 7 MB.\n* JSON.decode(body) returns {:ok, ...} after about one second of CPU.\n* JSON.decode(String.duplicate(\"9\", 1_000_000)) takes 100 to 300 times as long as JSON.decode(\"\\\"\" \u003c\u003e String.duplicate(\"9\", 1_000_000) \u003c\u003e \"\\\"\").\n* JSON.decode(String.duplicate(\"9\", 1_400_000)) raises SystemLimitError."
}
],
"x_technicalAnalysis": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003cstrong\u003e1. Default integer decoder\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eJSON.decode/1\u003c/code\u003e and \u003ccode\u003eJSON.decode!/1\u003c/code\u003e call \u003ccode\u003eJSON.decode/3\u003c/code\u003e without an \u003ccode\u003einteger\u003c/code\u003e decoder. Up to the removal of Erlang/OTP 26 support, \u003ccode\u003eJSON.decode/3\u003c/code\u003e used the vendored \u003ccode\u003eelixir_json\u003c/code\u003e module, whose default is \u003ccode\u003efun erlang:binary_to_integer/1\u003c/code\u003e. It now calls OTP\u0027s \u003ccode\u003e:json.decode/3\u003c/code\u003e, which has the same default. The \u003ccode\u003eJSON.decode/3\u003c/code\u003e documentation names \u003ccode\u003e\u0026amp;String.to_integer/1\u003c/code\u003e as the default, which converts the same way.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Unbounded conversion\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises \u003ccode\u003eSystemLimitError\u003c/code\u003e, which \u003ccode\u003eJSON.decode/3\u003c/code\u003e does not catch.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Reach\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ephx.new\u003c/code\u003e sets \u003ccode\u003econfig :phoenix, :json_library, JSON\u003c/code\u003e, and the generated endpoint passes \u003ccode\u003ePhoenix.json_library()\u003c/code\u003e to \u003ccode\u003ePlug.Parsers\u003c/code\u003e as \u003ccode\u003ejson_decoder\u003c/code\u003e. \u003ccode\u003ePlug.Parsers\u003c/code\u003e runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the \u003ccode\u003eSystemLimitError\u003c/code\u003e into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its \u003ccode\u003edecoding_integer_digit_limit\u003c/code\u003e (1024 by default) before conversion.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "**1. Default integer decoder**\n\n`JSON.decode/1` and `JSON.decode!/1` call `JSON.decode/3` without an `integer` decoder. Up to the removal of Erlang/OTP 26 support, `JSON.decode/3` used the vendored `elixir_json` module, whose default is `fun erlang:binary_to_integer/1`. It now calls OTP\u0027s `:json.decode/3`, which has the same default. The `JSON.decode/3` documentation names `\u0026String.to_integer/1` as the default, which converts the same way.\n\n**2. Unbounded conversion**\n\nThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises `SystemLimitError`, which `JSON.decode/3` does not catch.\n\n**3. Reach**\n\n`phx.new` sets `config :phoenix, :json_library, JSON`, and the generated endpoint passes `Phoenix.json_library()` to `Plug.Parsers` as `json_decoder`. `Plug.Parsers` runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the `SystemLimitError` into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its `decoding_integer_digit_limit` (1024 by default) before conversion."
}
],
"value": "1. Default integer decoder\n\nJSON.decode/1 and JSON.decode!/1 call JSON.decode/3 without an integer decoder. Up to the removal of Erlang/OTP 26 support, JSON.decode/3 used the vendored elixir_json module, whose default is fun erlang:binary_to_integer/1. It now calls OTP\u0027s :json.decode/3, which has the same default. The JSON.decode/3 documentation names \u0026String.to_integer/1 as the default, which converts the same way.\n\n2. Unbounded conversion\n\nThe decoder scans the digits of an integer literal and passes the whole run to the conversion. Nothing limits the run\u0027s length, so the cost grows faster than linearly with the number of digits. At one million digits an integer literal costs 100 to 300 times as much CPU as a string literal of the same length. Above about 1.29 million digits the conversion raises SystemLimitError, which JSON.decode/3 does not catch.\n\n3. Reach\n\nphx.new sets config :phoenix, :json_library, JSON, and the generated endpoint passes Phoenix.json_library() to Plug.Parsers as json_decoder. Plug.Parsers runs before routing and authentication and accepts bodies up to 8 MB by default. It rescues the SystemLimitError into a 400 response after the CPU cost is spent. Jason, the previous default, rejects integer literals longer than its decoding_integer_digit_limit (1024 by default) before conversion."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-115274",
"datePublished": "2026-10-30T08:57:16.847Z",
"dateReserved": "2026-10-23T12:45:01.103Z",
"dateUpdated": "2026-10-30T16:51:45.396Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
}
}
Loading…
Loading…
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
Loading…
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Loading…
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.