Uncontrolled recursion in elixir-protobuf/protobuf JSON decoding of self-referential messages
## Summary Uncontrolled Recursion vulnerability in `Protobuf.JSON.Decode` in elixir-protobuf protobuf allows an unauthenticated remote attacker to crash the decoding process via a deeply nested JSON document. Any application that decodes attacker-supplied JSON with `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, or `Protobuf.JSON.from_decoded/3` into a schema that contains a self-referential or cyclic message type is affected. In `lib/protobuf/json/decode.ex`, the embedded-message clause of `decode_singular/3` recurses into `internal_from_json_data/3` once per nesting level without incrementing or checking the decoder's depth counter. The depth guard `increase_depth_and_maybe_throw/1` covers only the `Google.Protobuf.ListValue` and `Google.Protobuf.Struct` clauses, so the `recursion_limit` option has no effect on user-defined message types. Each nesting level allocates a stack frame and heap objects, and a sufficiently deep document exhausts the memory of the decoding process. Confidentiality and integrity are not affected. This issue affects protobuf: from 0.8.0 before 0.17.1. ## Details **1. Entry points.** `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, and `Protobuf.JSON.from_decoded/3` in `lib/protobuf/json.ex` validate options and call `Protobuf.JSON.Decode.from_json_data/3`, which builds a `state` map carrying `depth: 0` and the `recursion_limit` (default 100). `from_decoded/3` accepts already-parsed data, so the underlying JSON parser never bounds the depth
- Products
- protobuf
- Affected versions
- 0.10.0, 0.11.0, 0.12.0, 0.13.0, 0.14.0, 0.14.1, 0.15.0, 0.16.0, 0.16.1, 0.17.0, 0.8.0, 0.9.0
- Fixed versions
- 0.17.1
- CVEs
- CVE-2026-104635
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 28 Oct 2026, 11:06 UTC · Revision 1
Source evidence
Uncontrolled recursion in elixir-protobuf/protobuf JSON decoding of self-referential messages
core-osv · Original sourcePublished 9 Oct 2026, 08:17 UTC
## Summary Uncontrolled Recursion vulnerability in `Protobuf.JSON.Decode` in elixir-protobuf protobuf allows an unauthenticated remote attacker to crash the decoding process via a deeply nested JSON document. Any application that decodes attacker-supplied JSON with `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, or `Protobuf.JSON.from_decoded/3` into a schema that contains a self-referential or cyclic message type is affected. In `lib/protobuf/json/decode.ex`, the embedded-message clause of `decode_singular/3` recurses into `internal_from_json_data/3` once per nesting level without incrementing or checking the decoder's depth counter. The depth guard `increase_depth_and_maybe_throw/1` covers only the `Google.Protobuf.ListValue` and `Google.Protobuf.Struct` clauses, so the `recursion_limit` option has no effect on user-defined message types. Each nesting level allocates a stack frame and heap objects, and a sufficiently deep document exhausts the memory of the decoding process. Confidentiality and integrity are not affected. This issue affects protobuf: from 0.8.0 before 0.17.1. ## Details **1. Entry points.** `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, and `Protobuf.JSON.from_decoded/3` in `lib/protobuf/json.ex` validate options and call `Protobuf.JSON.Decode.from_json_data/3`, which builds a `state` map carrying `depth: 0` and the `recursion_limit` (default 100). `from_decoded/3` accepts already-parsed data, so the underlying JSON parser never bounds the depth
osv:EEF-CVE-2026-104635
protobuf
Fixed versions: 0.17.1
Complete source record
{
"id": "fb390ce0c41c762e7649642accd6a0c8d23cf398e05663d063ab69399a3edcaa",
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-104635",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "Uncontrolled recursion in elixir-protobuf/protobuf JSON decoding of self-referential messages",
"summary": "## Summary Uncontrolled Recursion vulnerability in `Protobuf.JSON.Decode` in elixir-protobuf protobuf allows an unauthenticated remote attacker to crash the decoding process via a deeply nested JSON document. Any application that decodes attacker-supplied JSON with `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, or `Protobuf.JSON.from_decoded/3` into a schema that contains a self-referential or cyclic message type is affected. In `lib/protobuf/json/decode.ex`, the embedded-message clause of `decode_singular/3` recurses into `internal_from_json_data/3` once per nesting level without incrementing or checking the decoder's depth counter. The depth guard `increase_depth_and_maybe_throw/1` covers only the `Google.Protobuf.ListValue` and `Google.Protobuf.Struct` clauses, so the `recursion_limit` option has no effect on user-defined message types. Each nesting level allocates a stack frame and heap objects, and a sufficiently deep document exhausts the memory of the decoding process. Confidentiality and integrity are not affected. This issue affects protobuf: from 0.8.0 before 0.17.1. ## Details **1. Entry points.** `Protobuf.JSON.decode/3`, `Protobuf.JSON.decode!/3`, and `Protobuf.JSON.from_decoded/3` in `lib/protobuf/json.ex` validate options and call `Protobuf.JSON.Decode.from_json_data/3`, which builds a `state` map carrying `depth: 0` and the `recursion_limit` (default 100). `from_decoded/3` accepts already-parsed data, so the underlying JSON parser never bounds the depth ",
"evidence": "osv:EEF-CVE-2026-104635",
"products": [
{
"name": {
"value": "protobuf",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "0.17.1",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": [
{
"value": "0.10.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.11.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.12.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.13.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.14.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.14.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.15.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.16.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.16.1",
"evidence": "/affected/0/versions"
},
{
"value": "0.17.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.8.0",
"evidence": "/affected/0/versions"
},
{
"value": "0.9.0",
"evidence": "/affected/0/versions"
}
]
}
],
"severity": "high",
"structured": {
"id": "EEF-CVE-2026-104635",
"aliases": [
"CVE-2026-104635",
"EEF-CVE-2026-104635",
"GHSA-m497-c2h9-rvw6"
],
"metrics": [
{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0.8.0"
},
{
"fixed": "0.17.1"
}
]
}
],
"package": {
"name": "protobuf",
"purl": "pkg:hex/protobuf",
"ecosystem": "Hex"
},
"versions": [
"0.10.0",
"0.11.0",
"0.12.0",
"0.13.0",
"0.14.0",
"0.14.1",
"0.15.0",
"0.16.0",
"0.16.1",
"0.17.0",
"0.8.0",
"0.9.0"
],
"database_specific": {
"source": "https://cna.erlef.org/osv/EEF-CVE-2026-104635.json"
}
},
{
"ranges": [
{
"repo": "https://github.com/elixir-protobuf/protobuf",
"type": "GIT",
"events": [
{
"introduced": "b0a1d4eaffaf50012fa71a8e931a47cf252d0370"
},
{
"fixed": "e9432ad1c4099511905353cebcececa3a1f7c3ff"
}
]
}
],
"versions": [
"v0.17.0",
"v0.16.0",
"v0.15.0",
"v0.14.1",
"v0.14.0",
"v0.13.0",
"v0.12.0",
"v0.11.0",
"v0.10.0",
"v0.9.0",
"v0.8.0"
],
"database_specific": {
"source": "https://cna.erlef.org/osv/EEF-CVE-2026-104635.json"
}
}
],
"modified": "2026-10-09T09:30:02.783183553Z",
"provider": "osv",
"references": [
"https://github.com/elixir-protobuf/protobuf/security/advisories/GHSA-m497-c2h9-rvw6",
"https://cna.erlef.org/cves/CVE-2026-104635.html",
"https://github.com/elixir-protobuf/protobuf/commit/b0a1d4eaffaf50012fa71a8e931a47cf252d0370",
"https://github.com/elixir-protobuf/protobuf/commit/e9432ad1c4099511905353cebcececa3a1f7c3ff",
"https://hex.pm/packages/protobuf"
],
"provider_metadata": {
"cpe_ids": [
"cpe:2.3:a:elixir-protobuf:protobuf:*:*:*:*:*:*:*:*"
],
"cwe_ids": [
"CWE-674"
],
"capec_ids": [
"CAPEC-230"
]
}
},
"related_cves": [
{
"value": "CVE-2026-104635",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 111388,
"published_at": "2026-10-09T08:17:52.372+00:00"
}