iskorotkov/avro: CPU Exhaustion in Avro Decoder
Exploitation and risk
Source statusCISA KEV lists vulnerabilities known to be exploited. FIRST EPSS estimates the likelihood of exploitation in the next 30 days. An unavailable score does not mean zero risk.
Which CVEs have scores here?
This view includes predictions for CVE identifiers explicitly listed in public NuGet advisories. Microsoft release pages have their own prediction coverage. Check source status for the scope and latest checks.
No exploitation or prediction data is available here for these CVEs. This does not mean they are safe or unlikely to be exploited.
cve-program · CVE-2026-46385
Publishediskorotkov/avro is a fast Go Avro codec. Prior to 2.33.0, the Avro array and map decoders looped over an attacker-controlled block-count value without checking the underlying reader's error state inside the loop body. Reader.ReadBlockHeader returns the count as a Go int, which is 64-bit on amd64 / arm64 targets — so a producer can declare a block of up to math.MaxInt64 (~9.2 × 10¹⁸) elements followed by EOF (or any truncated payload), and the decoder will attempt that many no-op iterations before propagating the error. The realistic ceiling is "indefinite until the worker is killed externally" — a single hostile payload pins a CPU core until the process is OOM-killed, deadline-cancelled, or terminated. Remote, unauthenticated denial-of-service. This vulnerability is fixed in 2.33.0.
- Source published
- 29 May 2026 19:58:59 UTC
- Source modified
- 9 Sep 2026 12:05:07 UTC
- Saved here
- 23 Oct 2026 15:48:27 UTC
- Source terms
- CVE Program Terms of Use
Original source record · Cite this exact observation · Complete original publisher JSON
Source: cve-program · CVE Program Terms of Use. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
euvd · EUVD-2026-33444
Publishediskorotkov/avro is a fast Go Avro codec. Prior to 2.33.0, the Avro array and map decoders looped over an attacker-controlled block-count value without checking the underlying reader's error state inside the loop body. Reader.ReadBlockHeader returns the count as a Go int, which is 64-bit on amd64 / arm64 targets — so a producer can declare a block of up to math.MaxInt64 (~9.2 × 10¹⁸) elements followed by EOF (or any truncated payload), and the decoder will attempt that many no-op iterations before propagating the error. The realistic ceiling is "indefinite until the worker is killed externally" — a single hostile payload pins a CPU core until the process is OOM-killed, deadline-cancelled, or terminated. Remote, unauthenticated denial-of-service. This vulnerability is fixed in 2.33.0.
Additional publisher context
EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.
Original publisher date fields
datePublished: May 29, 2026, 7:58:59 PM
dateUpdated: Sep 9, 2026, 12:05:07 PM
9 related source bulletins · separate from aliases
RHSA-2026:53530: Red Hat Security Advisory: Multicluster Global Hub 1.7.2 security update
CVE-2026-27145 · CVE-2026-33376 · CVE-2026-33377 · CVE-2026-33811 · CVE-2026-39821 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-42306 · CVE-2026-43870 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-53492 · CVE-2026-55677 · CVE-2026-55969 · CVE-2026-66801
RHSA-2026:41064: Red Hat Security Advisory: Red Hat Advanced Cluster Management for Kubernetes v2.11.10 security update
CVE-2025-9288 · CVE-2025-13465 · CVE-2026-21721 · CVE-2026-22029 · CVE-2026-25639 · CVE-2026-42508 · CVE-2026-44486 · CVE-2026-44487 · CVE-2026-44488 · CVE-2026-44492 · CVE-2026-44494 · CVE-2026-44495 · CVE-2026-44496 · CVE-2026-44990 · CVE-2026-46384 · CVE-2026-46385
RHSA-2026:47149: Red Hat Security Advisory: Multicluster Global Hub 1.7.2 security update
CVE-2026-27145 · CVE-2026-33376 · CVE-2026-33377 · CVE-2026-33811 · CVE-2026-39821 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-43870 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-53492 · CVE-2026-55677
RHSA-2026:42852: Red Hat Security Advisory: Multicluster Global Hub 1.5.6 security update
CVE-2026-25681 · CVE-2026-27136 · CVE-2026-33376 · CVE-2026-33377 · CVE-2026-33811 · CVE-2026-39821 · CVE-2026-41567 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-43870 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-53492
RHSA-2026:44622: Red Hat Security Advisory: Multicluster Global Hub 1.6.4 security update
CVE-2026-25681 · CVE-2026-27136 · CVE-2026-27145 · CVE-2026-33376 · CVE-2026-33377 · CVE-2026-33811 · CVE-2026-39821 · CVE-2026-41567 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-43870 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-53492 · CVE-2026-55677
RHSA-2026:57191: Red Hat Security Advisory: Red Hat Advanced Cluster Management for Kubernetes v2.16.3 security update
CVE-2026-13676 · CVE-2026-14362 · CVE-2026-25681 · CVE-2026-27136 · CVE-2026-33377 · CVE-2026-33811 · CVE-2026-33814 · CVE-2026-39828 · CVE-2026-39829 · CVE-2026-42151 · CVE-2026-42502 · CVE-2026-42504 · CVE-2026-44486 · CVE-2026-44487 · CVE-2026-44488 · CVE-2026-44492 · CVE-2026-44494 · CVE-2026-44495 · CVE-2026-44496 · CVE-2026-44740 · CVE-2026-44990 · CVE-2026-45623 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-59869 · CVE-2026-66799 · CVE-2026-66804 · CVE-2026-69153 · CVE-2026-73086
RHSA-2026:30651: Red Hat Security Advisory: Red Hat Advanced Cluster Management for Kubernetes v2.13.9 security update
CVE-2026-35206 · CVE-2026-39821 · CVE-2026-42154 · CVE-2026-43869 · CVE-2026-44486 · CVE-2026-44487 · CVE-2026-44488 · CVE-2026-44492 · CVE-2026-44494 · CVE-2026-44495 · CVE-2026-44496 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-46595
RHSA-2026:48151: Red Hat Security Advisory: Red Hat build of Cryostat security update
CVE-2026-6734 · CVE-2026-6860 · CVE-2026-9697 · CVE-2026-12143 · CVE-2026-12151 · CVE-2026-13149 · CVE-2026-25681 · CVE-2026-27136 · CVE-2026-33811 · CVE-2026-39828 · CVE-2026-39829 · CVE-2026-39830 · CVE-2026-39835 · CVE-2026-42504 · CVE-2026-44249 · CVE-2026-44290 · CVE-2026-44291 · CVE-2026-44292 · CVE-2026-44893 · CVE-2026-45416 · CVE-2026-45674 · CVE-2026-45736 · CVE-2026-45740 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-46595 · CVE-2026-46599 · CVE-2026-46625 · CVE-2026-47691 · CVE-2026-48043 · CVE-2026-48059 · CVE-2026-48779 · CVE-2026-50010 · CVE-2026-50559 · CVE-2026-54512 · CVE-2026-54513
RHSA-2026:41030: Red Hat Security Advisory: Multicluster Global Hub 1.4.7 security update
CVE-2026-25681 · CVE-2026-27136 · CVE-2026-27145 · CVE-2026-33811 · CVE-2026-39821 · CVE-2026-41567 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-43870 · CVE-2026-46384 · CVE-2026-46385 · CVE-2026-53488 · CVE-2026-53492
- Source published
- May 29, 2026, 7:58:59 PM (timezone not stated)
- Source modified
- Sep 9, 2026, 12:05:07 PM (timezone not stated)
- Saved here
- 13 Nov 2026 13:05:39 UTC
- Source terms
- ENISA EUVD · source terms and attribution apply
Original source record · Cite this exact observation · Complete original publisher JSON
Source: euvd · ENISA EUVD · source terms and attribution apply. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
EUVD CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
nvd · CVE-2026-46385
Publishediskorotkov/avro is a fast Go Avro codec. Prior to 2.33.0, the Avro array and map decoders looped over an attacker-controlled block-count value without checking the underlying reader's error state inside the loop body. Reader.ReadBlockHeader returns the count as a Go int, which is 64-bit on amd64 / arm64 targets — so a producer can declare a block of up to math.MaxInt64 (~9.2 × 10¹⁸) elements followed by EOF (or any truncated payload), and the decoder will attempt that many no-op iterations before propagating the error. The realistic ceiling is "indefinite until the worker is killed externally" — a single hostile payload pins a CPU core until the process is OOM-killed, deadline-cancelled, or terminated. Remote, unauthenticated denial-of-service. This vulnerability is fixed in 2.33.0.
Additional publisher context
NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.
Source analysis status: Deferred
Weakness classifications: CWE-400 · CWE-835
Original publisher date fields
published: 2026-05-29T20:16:27.990
lastModified: 2026-09-09T13:20:17.253
- Source published
- 29 May 2026 20:16:27 UTC
- Source modified
- 9 Sep 2026 13:20:17 UTC
- Saved here
- 25 Oct 2026 12:17:14 UTC
- Source terms
- NIST NVD usage terms; underlying source attribution retained
Original source record · Cite this exact observation · Complete original publisher JSON
Source: nvd · NIST NVD usage terms; underlying source attribution retained. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS 4.0 · [email protected] · Secondary · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/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
CVSS 3.1 · 0b0ca135-0b70-47e7-9f44-1890c2a1c46c · Secondary · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
osv · GHSA-w8j3-pq8g-8m7w
Published# CPU Exhaustion in Avro Decoder via Unbounded Block-Count Iteration ## Summary The Avro array and map decoders looped over an attacker-controlled block-count value without checking the underlying reader's error state inside the loop body. `Reader.ReadBlockHeader` returns the count as a Go `int`, which is 64-bit on `amd64` / `arm64` targets — so a producer can declare a block of up to `math.MaxInt64` (~9.2 × 10¹⁸) elements followed by EOF (or any truncated payload), and the decoder will attempt that many no-op iterations before propagating the error. The realistic ceiling is "indefinite until the worker is killed externally" — a single hostile payload pins a CPU core until the process is OOM-killed, deadline-cancelled, or terminated. Remote, unauthenticated denial-of-service. The fix exits the loop on the first inner-decode error. It does not bound the loop length itself; for full coverage on untrusted inputs, also configure `Config.MaxSliceAllocSize` and `Config.MaxMapAllocSize` (the latter introduced in `v2.33.0`). ## Description Avro arrays and maps are encoded as one or more blocks; each block declares an element count followed by that many encoded elements. The decoder reads the block count as a zigzag-encoded `long`, then iterates that many times calling an inner decoder. Three iteration sites trusted the block count without checking the reader's accumulated error state between iterations: - `codec_skip.go` `sliceSkipDecoder.Decode` — skip helper for arrays. - `codec_skip.go` `mapSkipDecoder.Decode` — skip helper for maps. - `reader_generic.go` `Reader.ReadArrayCB` and `Reader.ReadMapCB` — callback-based decoders used by generic and unmarshaling code paths. Because the inner `Decode(nil, r)` call is a no-op when `r` has already errored (it returns immediately without consuming bytes), the loop would run to completion even after the first iteration's EOF. On `amd64` / `arm64`, `Reader.ReadBlockHeader` returns the count as `int` (= `int64`), so the loop bound is whatever the wire payload specified, up to `math.MaxInt64`. A modest 200-million-count payload (well under 2³¹) already burns several seconds; a `math.MaxInt − 2` payload (the value used in the regression test `TestDecoder_ArrayMultiBlockExceedsMaxInt` from PR #9) effectively pins the goroutine until external kill. This overlaps with [`GHSA-mc57-h6j3-3hmv`](https://github.com/iskorotkov/avro/security/advisories/GHSA-mc57-h6j3-3hmv): the same large-block-count payload that drives the unbounded loop here also drives the cumulative-arithmetic overflow there (cross-platform), and on a 32-bit target additionally triggers the union-index / byte-slice narrowing. ## Affected components | File | Function | PR | Fix commit | |------|----------|----|------------| | `codec_skip.go` | `sliceSkipDecoder.Decode` | — | [`b124caa`](https://github.com/iskorotkov/avro/commit/b124caa58a821f68f100d86f045f9753b88881e8) | | `codec_skip.go` | `mapSkipDecoder.Decode` | — | [`b124caa`](https://github.com/iskorotkov/avro/commit/b124caa58a821f68f100d86f045f9753b88881e8) | | `reader_generic.go` | `Reader.ReadArrayCB` | [#4](https://github.com/iskorotkov/avro/pull/4) | [`2ce4242`](https://github.com/iskorotkov/avro/commit/2ce4242e6095d93470ab3b37ed6082b0596f325c) | | `reader_generic.go` | `Reader.ReadMapCB` | [#4](https://github.com/iskorotkov/avro/pull/4) | [`2ce4242`](https://github.com/iskorotkov/avro/commit/2ce4242e6095d93470ab3b37ed6082b0596f325c) | These are the audited and patched sites. Any other code path that iterates over an attacker-controlled count while calling a `Reader`-style decoder is structurally susceptible to the same pattern; reviewers of consumer code should grep for `for range l` / `for i := 0; i < int(l); i++` near `Reader` method calls and confirm an in-loop error check. ## Technical details **Vulnerable pattern:** ```go for range l { d.decoder.Decode(nil, r) // r.Error may have been set by Decode; loop continues regardless. } ``` After `r.Error != nil`, subsequent `Decode` calls short-circuit and return without consuming bytes or doing useful work, but the loop control variable still runs to `l`. With `l = math.MaxInt64`, the loop body executes ~9.2 × 10¹⁸ times — effectively infinite for any realistic timeout. **Fixed pattern** ([`b124caa`](https://github.com/iskorotkov/avro/commit/b124caa58a821f68f100d86f045f9753b88881e8), [`2ce4242`](https://github.com/iskorotkov/avro/commit/2ce4242e6095d93470ab3b37ed6082b0596f325c)): ```go for range l { d.decoder.Decode(nil, r) if r.Error != nil { break } } ``` The fix terminates the loop on the first inner error. It does **not** bound `l` itself — a well-formed payload that actually contains `N` encoded `null` elements still iterates `N` times. The `MaxSliceAllocSize` / `MaxMapAllocSize` caps are the policy-level bound on that case (see Mitigation). ## Fixed behavior The reader's accumulated error is checked after every inner `Decode` in the four affected loops. Decoder errors now surface in O(1) iterations instead of O(blockCount) when the underlying read fails mid-stream. ## Affected versions - `github.com/hamba/avro/v2` — all versions up to and including `v2.31.0` (repository is read-only upstream). - `github.com/iskorotkov/avro/v2` — all versions prior to `v2.33.0`. ## Fixed versions `github.com/iskorotkov/avro/v2` `v2.33.0` and later. There is no upstream fix for `github.com/hamba/avro/v2` — module path is archived. Migrate to the fork as described under Mitigation. ## Mitigation Migrate from `github.com/hamba/avro/v2` to `github.com/iskorotkov/avro/v2 >= v2.33.0`. Replace the import path and run `go mod tidy`: ```bash go get github.com/iskorotkov/avro/v2@latest ``` Or, for consumers that prefer the original import path, a `replace` directive in `go.mod`: ``` replace github.com/hamba/avro/v2 => github.com/iskorotkov/avro/v2 v2.33.0 ``` `replace` is honoured only for the **main** module of a build — transitive consumers must add their own `replace`, or migrate the import path directly. The error-propagation fix runs on the existing decode path and requires no configuration. For defense-in-depth against well-formed but oversized payloads (where the fix above does not help, because no error fires), set explicit allocation caps: ```go cfg := avro.Config{ MaxByteSliceSize: 102_400, MaxSliceAllocSize: 10_000, MaxMapAllocSize: 10_000, }.Freeze() decoder := cfg.NewDecoder(schema, reader) ``` `MaxMapAllocSize` is new in `v2.33.0` and opt-in (default zero, which leaves the previous unbounded behavior). Without setting it, a producer that ships a `math.MaxInt64`-count block still consumes the corresponding memory and CPU; see [`GHSA-mx64-mj3q-7prj`](https://github.com/iskorotkov/avro/security/advisories/GHSA-mx64-mj3q-7prj) for the cumulative-allocation enforcement details. If you cannot upgrade immediately, the structural workarounds are application-level: per-request decode timeouts, isolated decoder workers under CPU quotas, and rejection of payloads whose advertised block count exceeds a known sane bound for your schema. ## Proof-of-concept input A minimal payload that triggers the bug for an array of `int`: ``` zigzag-encoded long: math.MaxInt64 (block element count) EOF (no further bytes) ``` The decoder reads the block-count header, enters the loop, fails to read the first element (EOF), records the error, and then iterates `math.MaxInt64 − 1` further times calling the inner decoder as a no-op. Wall-clock cost on commodity hardware: indefinite — the goroutine pins one CPU core until the process is OOM-killed, deadline-cancelled, or terminated externally. The classic *"a few seconds per request"* characterisation applies only to small-but-still-pathological block counts in the 10⁸–10⁹ range (e.g. `200_999_000` in `TestDecoder_SkipArrayEOF`); the architectural ceiling is `math.MaxInt64`. A negative block count (`-N`) is also legal in Avro (signals an N-element block with an explicit byte length); the same iteration pattern applies once the count is negated. ## References - Fix PR: [iskorotkov/avro#4](https://github.com/iskorotkov/avro/pull/4) (callback path) - Fix commits: [`b124caa`](https://github.com/iskorotkov/avro/commit/b124caa58a821f68f100d86f045f9753b88881e8) (skip helpers), [`2ce4242`](https://github.com/iskorotkov/avro/commit/2ce4242e6095d93470ab3b37ed6082b0596f325c) (callback path) - Release: [`v2.33.0`](https://github.com/iskorotkov/avro/releases/tag/v2.33.0) - Security policy: [`SECURITY.md`](https://github.com/iskorotkov/avro/blob/main/SECURITY.md) - Related advisories on this fork: [`GHSA-mc57-h6j3-3hmv`](https://github.com/iskorotkov/avro/security/advisories/GHSA-mc57-h6j3-3hmv) (integer overflow — same large-block-count payload also triggers cumulative-arithmetic overflow there), [`GHSA-mx64-mj3q-7prj`](https://github.com/iskorotkov/avro/security/advisories/GHSA-mx64-mj3q-7prj) (unbounded map allocation — the policy-level bound on well-formed huge inputs) - Cross-module precedent on `hamba/avro`: [`GO-2023-1930`](https://pkg.go.dev/vuln/GO-2023-1930) / `CVE-2023-37475` / `GHSA-9x44-9pgq-cf45` - Upstream (read-only): [`hamba/avro`](https://github.com/hamba/avro) ## Credits - **Discovery and fixes** (commits `b124caa` skip helpers and `2ce4242` callback path, PR #4): Daniel Błażewicz ([@klajok](https://github.com/klajok)) - **Release authorship**: Ivan Korotkov ([@iskorotkov](https://github.com/iskorotkov)) ## Timeline - **2026-04-28** — Skip-decoder fix (`b124caa`) merged. - **2026-04-30** — Callback-decoder fix (PR #4, `2ce4242`) merged. - **2026-05-06** — `v2.33.0` tagged and released. - **2026-05-11** — Advisory published. - **2026-05-15** — Advisory revised.
- Source published
- 18 May 2026 16:33:43 UTC
- Source modified
- 10 Sep 2026 03:50:47 UTC
- Saved here
- 24 Oct 2026 13:19:41 UTC
- Source terms
- GitHub Advisory Database · CC-BY-4.0
Original source record · Cite this exact observation · Complete original publisher JSON
Source: osv · GitHub Advisory Database · CC-BY-4.0. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.
CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Publisher rating · HIGH
osv · GO-2026-5046
PublishedThe Avro array and map decoders loop over an attacker-controlled block-count value without checking the underlying reader's error state inside the loop body. Reader.ReadBlockHeader returns the count as a Go int, which is 64-bit on amd64 and arm64 targets. A producer can declare a block of up to math.MaxInt64 elements followed by EOF or any truncated payload, and the decoder will attempt that many no-op iterations before propagating the error. The realistic ceiling is indefinite until the worker is killed externally. A single hostile payload pins a CPU core until the process is OOM-killed, deadline-cancelled, or terminated, resulting in a remote, unauthenticated denial-of-service. The fix exits the loop on the first inner-decode error.
- Source published
- 27 Jul 2026 16:16:22 UTC
- Source modified
- 5 Aug 2026 03:41:56 UTC
- Saved here
- 24 Oct 2026 13:19:41 UTC
- Source terms
- OSV · upstream source license applies
Original source record · Cite this exact observation · Complete original publisher JSON
Source: osv · OSV · upstream source license applies. The publisher's wording is preserved. ChangeIntel groups the information and labels changes. The JSON record includes additional source fields.