{"id":"GHSA-jh4v-gfqj-7rhx","summary":"RabbitMQ Java client has frame-level OOM: Math.min(maxInboundMessageBodySize, 0) defeats frame size enforcement","details":"## Vulnerability\n\nIn `AMQConnection.java` (line 435-436), after `Connection.Tune` negotiation, the frame-max limit is set via:\n\n```java\n_frameHandler.setFrameMax(\n    Math.min(this.maxInboundMessageBodySize, frameMax));\n```\n\nWhen `frameMax = 0` (meaning \"unlimited\" per AMQP spec), `Math.min(67108864, 0) = 0`. This value is then passed to `Utils.framePayloadLimit(0)` which returns `Integer.MAX_VALUE` (line 77-79 of Utils.java):\n\n```java\nstatic int framePayloadLimit(int frameMax) {\n    if (frameMax \u003c= 0) {\n      return Integer.MAX_VALUE;\n    }\n    // ...\n}\n```\n\nThis completely defeats the `maxInboundMessageBodySize` protection (default 64MB) at the frame level.\n\n## Attack Scenario\n\nA malicious AMQP server (or MITM) sends `Connection.Tune` with `frameMax=0`:\n\n1. Client defaults: `requestedFrameMax = 0` (`ConnectionFactory.DEFAULT_FRAME_MAX`, line 82)\n2. `negotiatedMaxValue(0, 0)` = `Math.max(0, 0)` = 0 (line 673-676)\n3. `Math.min(maxInboundMessageBodySize, 0)` = 0 — **64MB cap defeated**\n4. `framePayloadLimit(0)` = `Integer.MAX_VALUE` — no frame size enforcement\n5. Attacker sends a single frame with `frameSize = 0x1FFFFFFF` (~500MB)\n6. `Frame.readFrom()` (line 135) executes `new byte[frameSize]` — **OOM crash**\n\nThe frame does not need to be a body frame — method frames, header frames, or heartbeat frames with a crafted size field all trigger the allocation before any content-level check fires.\n\n## Root Cause\n\nThe AMQP spec uses `frameMax=0` to mean \"unlimited\", but `Math.min` treats it as the integer value zero. The intent of line 435-436 was to take the smaller of the two limits, but when one limit uses 0-means-unlimited semantics, `Math.min` always selects the zero, disabling the other limit.\n\n## Impact\n\n- **Default configuration is vulnerable**: Both `requestedFrameMax` (client) and legitimate servers' `frameMax` in Tune may be 0\n- **Single-frame OOM**: One malicious frame triggers up to ~2GB allocation (`Integer.MAX_VALUE` bytes)\n- **Bypasses existing protection**: `maxInboundMessageBodySize` (introduced to cap allocations at 64MB) is entirely defeated at the frame level\n- **Different from ValueReader OOM**: This is a frame-layer allocation in `Frame.readFrom()`, not a value-layer allocation in `ValueReader.readBytes()`\n\n## Affected Code\n\n- `AMQConnection.java:435-436` — `Math.min` with 0-means-unlimited\n- `Utils.java:77-79` — `framePayloadLimit(0)` returns `Integer.MAX_VALUE`\n- `Frame.java:135` — `new byte[frameSize]` allocation site\n- `ConnectionFactory.java:82` — `DEFAULT_FRAME_MAX = 0`\n\n## Suggested Fix\n\n```java\nint effectiveFrameMax = (frameMax == 0)\n    ? this.maxInboundMessageBodySize\n    : Math.min(this.maxInboundMessageBodySize, frameMax);\n_frameHandler.setFrameMax(effectiveFrameMax);\n```\n\nThis treats `frameMax=0` as \"use maxInboundMessageBodySize as the cap\" instead of \"zero\".","aliases":["CVE-2026-75516"],"modified":"2026-09-17T15:00:05.192737461Z","published":"2026-09-17T14:52:21Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2026-09-17T14:52:21Z","nvd_published_at":"2026-09-16T19:17:33Z","cwe_ids":["CWE-770"],"severity":"HIGH"},"references":[{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/security/advisories/GHSA-jh4v-gfqj-7rhx"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-75516"},{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/pull/2015"},{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/pull/2016"},{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/commit/6d7c2bfe89796ca34d3531098fb59dd657fea39e"},{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/commit/e7f10bf99aee103dd9f64b3e52a725fc9f9d3763"},{"type":"PACKAGE","url":"https://github.com/rabbitmq/rabbitmq-java-client"},{"type":"WEB","url":"https://github.com/rabbitmq/rabbitmq-java-client/releases/tag/v5.34.0"}],"affected":[{"package":{"name":"com.rabbitmq:amqp-client","ecosystem":"Maven","purl":"pkg:maven/com.rabbitmq/amqp-client"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"5.34.0"}]}],"versions":["1.3.0","1.5.4","1.5.5","1.6.0","1.7.2","1.8.0","1.8.1","2.0.0","2.1.0","2.1.1","2.2.0","2.3.0","2.3.1","2.4.1","2.5.0","2.5.1","2.6.0","2.6.1","2.7.0","2.7.1","2.8.0","2.8.1","2.8.2","2.8.3","2.8.4","2.8.5","2.8.6","2.8.7","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4","3.2.0","3.2.1","3.2.2","3.2.3","3.2.4","3.3.0","3.3.1","3.3.2","3.3.3","3.3.4","3.3.5","3.4.0","3.4.1","3.4.2","3.4.3","3.4.4","3.5.0","3.5.1","3.5.2","3.5.3","3.5.4","3.5.5","3.5.6","3.5.7","3.6.0","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","4.0.0","4.0.1","4.0.2","4.0.3","4.1.0","4.1.1","4.10.0","4.11.0","4.11.1","4.11.2","4.11.3","4.12.0","4.2.0","4.2.1","4.2.2","4.3.0","4.4.0","4.4.1","4.4.2","4.5.0","4.6.0","4.7.0","4.8.0","4.8.1","4.8.2","4.8.3","4.9.0","4.9.1","4.9.2","4.9.3","5.0.0","5.1.0","5.1.1","5.1.2","5.10.0","5.11.0","5.12.0","5.13.0","5.13.1","5.14.0","5.14.1","5.14.2","5.14.3","5.15.0","5.16.0","5.16.1","5.17.0","5.17.1","5.18.0","5.19.0","5.2.0","5.20.0","5.21.0","5.22.0","5.23.0","5.24.0","5.25.0","5.26.0","5.27.0","5.27.1","5.28.0","5.29.0","5.3.0","5.30.0","5.31.0","5.32.0","5.33.0","5.33.1","5.4.0","5.4.1","5.4.2","5.4.3","5.5.0","5.5.1","5.5.2","5.5.3","5.6.0","5.7.0","5.7.1","5.7.2","5.7.3","5.8.0","5.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-jh4v-gfqj-7rhx/GHSA-jh4v-gfqj-7rhx.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"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"}]}