Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-45799

CVE-2026-45799: Wire gRPC Protocol Buffers DoS Vulnerability

CVE-2026-45799 is a denial of service flaw in Wire gRPC and protocol buffers library that allows attackers to crash services via crafted protobuf payloads. This post covers technical details, affected versions, and mitigation.

Published:

CVE-2026-45799 Overview

CVE-2026-45799 is a high-severity denial-of-service vulnerability in Square's Wire library, which provides gRPC and protocol buffer support for Android, Kotlin, Swift, and Java. The flaw resides in the wire-runtime component, specifically in ByteArrayProtoReader32.skipGroup() and ProtoReader.skipGroup(). These functions fail to validate that a LENGTH_DELIMITED field length is non-negative before invoking skip(). A crafted protobuf varint encoding -128 as a signed Int can drive the internal reader position negative, causing the next readByte() call to throw ArrayIndexOutOfBoundsException instead of the documented IOException or ProtocolException. Services calling ProtoAdapter.decode(byte[]) on untrusted payloads can crash.

Critical Impact

Unauthenticated remote attackers can crash services parsing untrusted protobuf payloads by sending a single malformed message, disrupting availability of gRPC endpoints and Kotlin/Java applications relying on Wire.

Affected Products

  • Square Wire wire-runtime versions prior to 6.3.0
  • Square Wire wire-runtime 7.x versions prior to 7.0.0-alpha03
  • Any Android, Kotlin, Swift, or Java service using ProtoAdapter.decode(byte[]) on untrusted input

Discovery Timeline

  • 2026-07-17 - CVE-2026-45799 published to NVD
  • 2026-07-23 - Last updated in NVD database

Technical Details for CVE-2026-45799

Vulnerability Analysis

The vulnerability is an improper validation of array index issue [CWE-129] in Wire's protobuf decoder. When Wire encounters a LENGTH_DELIMITED field inside skipGroup(), it reads a varint length using internalReadVarint32() and then calls skip(length) without verifying the value is non-negative. A specially encoded varint yields the signed integer -128, which propagates into skip() and rewinds the internal pos cursor into negative territory.

The subsequent readByte() operation indexes into the backing byte array with a negative offset, raising an unchecked ArrayIndexOutOfBoundsException. The Wire API contract documents IOException and ProtocolException as the only expected failure modes, so calling code typically does not catch runtime exceptions. Uncaught exceptions propagate up the call stack and terminate the request handler or service worker.

Root Cause

The root cause is missing bounds validation on user-controlled length fields inside skipGroup() in both ByteArrayProtoReader32.kt and ProtoReader.kt. The decoder trusts the varint value returned by internalReadVarint32() and passes it directly to skip() and to the pos counter arithmetic without confirming length >= 0.

Attack Vector

An attacker sends a crafted protobuf message to any endpoint that decodes untrusted payloads through ProtoAdapter.decode(byte[]). The message includes a nested group containing a LENGTH_DELIMITED tag whose varint length decodes to a negative signed 32-bit integer. No authentication or user interaction is required, and the attack traverses the network. The patch in commits 47d5b0d and e4e56fa inserts an explicit negative-length guard before skip().

kotlin
// Security patch in wire-runtime/src/commonMain/kotlin/com/squareup/wire/ProtoReader.kt
        }
        STATE_LENGTH_DELIMITED -> {
          val length = internalReadVarint32()
+         if (length < 0) throw ProtocolException("Negative length: $length. Reader position: $pos. Last read tag: $tag.")
          pos += length.toLong()
          source.skip(length.toLong())
        }

Source: square/wire commit 47d5b0d

kotlin
// Security patch in wire-runtime/src/commonMain/kotlin/com/squareup/wire/ByteArrayProtoReader32.kt
        }
        STATE_LENGTH_DELIMITED -> {
          val length = internalReadVarint32()
+         if (length < 0) throw ProtocolException("Negative length: $length. Reader position: $pos. Last read tag: $tag.")
          skip(length)
        }
        STATE_VARINT -> {

Source: square/wire commit e4e56fa

Detection Methods for CVE-2026-45799

Indicators of Compromise

  • Unhandled java.lang.ArrayIndexOutOfBoundsException stack traces originating from com.squareup.wire.ProtoReader.skipGroup or ByteArrayProtoReader32.skipGroup
  • Sudden service crashes or thread termination correlated with inbound gRPC or protobuf traffic
  • Repeated malformed protobuf decode failures from a single client IP or upstream source

Detection Strategies

  • Instrument protobuf decode call sites with structured logging that captures exception class, remote peer, and payload size for post-crash forensics.
  • Deploy application-layer monitoring on gRPC endpoints to flag decode errors exceeding baseline rates.
  • Perform software composition analysis to identify services depending on com.squareup.wire:wire-runtime at versions below 6.3.0 or 7.0.0-alpha03.

Monitoring Recommendations

  • Alert on JVM uncaught exception handlers reporting ArrayIndexOutOfBoundsException from Wire classes.
  • Track gRPC server error rates and thread pool exhaustion metrics for pattern shifts after deploying untrusted-facing endpoints.
  • Correlate crash telemetry with network capture of the offending request to confirm malformed varint payloads.

How to Mitigate CVE-2026-45799

Immediate Actions Required

  • Upgrade com.squareup.wire:wire-runtime to 6.3.0 or 7.0.0-alpha03 across all Android, Kotlin, Swift, and Java projects.
  • Audit dependency trees for transitive Wire usage in gRPC clients and servers that accept external traffic.
  • Restart affected services after upgrade to ensure the patched runtime is loaded.

Patch Information

The fix is available in Wire 6.3.0 and Wire 7.0.0-alpha03. Additional context is provided in GHSA-7xpr-hc2w-34m9, pull request #3595, and pull request #3597.

Workarounds

  • Wrap ProtoAdapter.decode(byte[]) calls in a try/catch that also handles RuntimeException and ArrayIndexOutOfBoundsException to prevent thread termination on malformed input.
  • Enforce a strict maximum message size at the gRPC or HTTP layer before payloads reach the Wire decoder.
  • Restrict protobuf endpoints to authenticated clients where feasible until the patched runtime is deployed.
bash
# Update Gradle dependency to the patched version
# build.gradle.kts
dependencies {
    implementation("com.squareup.wire:wire-runtime:6.3.0")
}

# Or for Maven pom.xml
# <dependency>
#   <groupId>com.squareup.wire</groupId>
#   <artifactId>wire-runtime</artifactId>
#   <version>6.3.0</version>
# </dependency>

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.