CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-XHJ4-G6W8-2XJW
7.5

CVE-2026-33524: Unbounded Memory Allocation in go-zserio

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 24, 2026·6 min read·4 visits

PoC Available

Executive Summary (TL;DR)

A critical flaw in go-zserio allows attackers to trigger massive memory allocations via forged length fields in incoming network payloads. This causes immediate Out-of-Memory crashes and Denial of Service. The vulnerability is patched by introducing bounded, incremental memory allocation.

The `go-zserio` library suffers from an Unbounded Memory Allocation vulnerability (CWE-770) during the deserialization of structured data. An unauthenticated remote attacker can trigger an immediate Out-of-Memory (OOM) crash by sending a crafted payload with a forged length field, resulting in a Denial of Service (DoS).

Vulnerability Overview

The go-zserio package is a Go implementation of the zserio serialization framework. It is responsible for parsing structured binary data from potentially untrusted sources. The library suffers from CWE-770, an Allocation of Resources Without Limits or Throttling vulnerability.

This vulnerability affects the deserialization logic specifically designed for arrays, strings, and byte arrays (blobs). An attacker can trigger a Denial of Service (DoS) condition by causing an Out-of-Memory (OOM) crash on the host system. The issue stems from trusting unvalidated length fields during byte stream parsing operations.

The flaw requires no authentication and minimal network bandwidth to exploit. Applications using vulnerable versions of go-zserio to process data from external networks are exposed to immediate service disruption. The vulnerability is structurally tied to the library's handling of zserio's varsize encoding scheme.

Root Cause Analysis

Zserio uses a variable-length encoding scheme known as varsize to define the size of dynamic data structures, such as arrays, strings, and external blobs. During deserialization, the library reads this length prefix from the incoming byte stream to determine the memory footprint required for the upcoming object. Prior to the patch, the parser accepted this length value without validating it against the remaining bytes in the stream or applying any global memory constraints.

The vulnerability manifests when the library translates the parsed varsize integer directly into a memory allocation request using the built-in Go make() function. The code executes operations such as make([]T, 0, size) or make([]byte, size) using the unverified size parameter derived entirely from the attacker-controlled input. If an attacker specifies an artificially large size, such as 0xFFFFFFFF, the Go runtime attempts to allocate several gigabytes of memory instantaneously.

Because this allocation occurs before the library attempts to read the corresponding payload data, the actual physical size of the incoming network packet is irrelevant. The application exhausts system memory resources purely based on the forged integer in the header. The discrepancy between the claimed size and the actual data available allows a multi-gigabyte allocation to be triggered by a packet consisting of only a few bytes.

Code Analysis

In the vulnerable implementation, the deserialization routine read the varsize integer and passed it directly to the slice initialization function. The code lacked any boundary checks or incremental growth strategies. This direct allocation approach is a known anti-pattern in network protocol parsers written in Go.

// Vulnerable pattern conceptually representing the flaw
length := readVarSize(stream)
// Instantly allocates memory based on unvalidated length
data := make([]byte, length) 
stream.Read(data)

The patch introduced in commit 39ef1decde7e9766207794d396018776b33c6e45 replaces the direct allocation strategy with a bounded, incremental approach. For string and byte array allocations, the library now employs a newly introduced safeReadBytes function. This function uses io.LimitReader and io.CopyBuffer to read data into a buffer that grows incrementally as data is actually received over the wire.

// Patched approach conceptually representing the fix
func safeReadBytes(r io.Reader, size int) ([]byte, error) {
    // Bounded limit prevents massive initial allocation
    lr := io.LimitReader(r, int64(size))
    var buf bytes.Buffer
    // Memory scales incrementally with actual data
    _, err := io.Copy(&buf, lr)
    return buf.Bytes(), err
}

For array structures, the initial slice capacity is now capped using min(arraySize, maxInitialArrayCapacityInt). The patch introduces environment variables to enforce these hard limits globally. The ZSERIO_MAX_INITIAL_ARRAY_SIZE defaults to 1000 elements, and ZSERIO_MAX_INITIAL_BLOB_SIZE defaults to 102400 bytes (100KB).

Exploitation

The exploitation methodology relies on sending a crafted zserio-encoded payload to a vulnerable network endpoint. An attacker constructs a binary message containing a valid structural header but modifies the varsize length field associated with a string, array, or external blob. The attacker sets this length field to an exceptionally large value, maximizing the integer size permitted by the target architecture.

The attacker transmits this compact payload to the target service. The application receives the packet and invokes standard parsing functions such as UnmarshalZserio, ReadBytes, or ReadString on the unvalidated data stream. The parser extracts the forged length and initiates the unsafe memory allocation sequence.

Since the payload is artificially small, the attacker requires minimal bandwidth and computational resources to execute the attack. The Go runtime processes the massive allocation request, leading to rapid memory exhaustion on the host. The host operating system's OOM killer subsequently intervenes and terminates the target process, resulting in an immediate denial of service.

Impact Assessment

The primary impact of CVE-2026-33524 is a complete loss of availability for the affected application. Because the vulnerability requires no authentication and relies on minimal network bandwidth, an unauthenticated attacker can repeatedly crash the service with negligible effort. This constitutes a high-severity Denial of Service (DoS) attack against any exposed endpoint.

The vulnerability carries an estimated CVSS v3.1 score of 7.5, reflecting the network attack vector, low attack complexity, and lack of required privileges (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). The impact is strictly limited to availability. The flaw does not facilitate arbitrary code execution, nor does it permit unauthorized access to sensitive data memory.

Applications utilizing go-zserio to process untrusted input over public networks face the highest risk of exploitation. Furthermore, internal microservices parsing zserio payloads originating from adjacent network segments remain vulnerable to lateral DoS attacks initiated by a compromised internal host.

Remediation

The primary remediation strategy requires upgrading the github.com/woven-by-toyota/go-zserio dependency. Organizations must ensure they deploy a version containing commit 39ef1decde7e9766207794d396018776b33c6e45 or later. This update inherently mitigates the unbounded allocation vector by enforcing the newly introduced default memory limits and incremental allocation strategies.

Developers must evaluate their specific application requirements against the newly established default limits. If an application legitimately processes arrays larger than 1000 elements or blobs exceeding 100KB, operators must adjust the ZSERIO_MAX_INITIAL_ARRAY_SIZE and ZSERIO_MAX_INITIAL_BLOB_SIZE environment variables accordingly. Setting these variables to 0 disables the limits entirely and should strictly be avoided for any application parsing untrusted input.

As an additional defense-in-depth measure, administrators should implement network-level constraints. Configuring API gateways, load balancers, or Web Application Firewalls (WAF) to enforce strict request size limits prevents anomalous, excessively large packets from reaching the application tier. This provides a secondary layer of protection against variant volumetric attacks.

Official Patches

woven-by-toyotaFix Commit implementing bounds checks and safeReadBytes

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Affected Systems

github.com/woven-by-toyota/go-zserio

Affected Versions Detail

Product
Affected Versions
Fixed Version
go-zserio
woven-by-toyota
< commit 39ef1decde7e9766207794d396018776b33c6e45commit 39ef1decde7e9766207794d396018776b33c6e45
AttributeDetail
Vulnerability ClassUnbounded Memory Allocation
CWE IDCWE-770
Attack VectorNetwork
CVSS v3.1 Score7.5
ImpactDenial of Service (Availability)
Privileges RequiredNone
Patch StatusPatched

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

The software allocates memory or other resources without any limits, which allows an attacker to exhaust available resources.

Vulnerability Timeline

Fix commit 39ef1decde7e9766207794d396018776b33c6e45 pushed to the repository.
2026-04-20
Advisory updated to reflect the OOM prevention measures.
2026-04-22

References & Sources

  • [1]GitHub Advisory: GHSA-XHJ4-G6W8-2XJW
  • [2]Patch Commit
  • [3]go-zserio Repository
Related Vulnerabilities
GHSA-XHJ4-G6W8-2XJW

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.