GitHub Advisoryadvisory · Go
GHSA-mmq5-xm89-9pfg imgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field
HIGH
Official page ↗
- Ecosystem
- Go
- Packages
- github.com/imgproxy/imgproxy/v3
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Weaknesses
- CWE-400
- Reviewed
- 2026-10-30
Affected packages
• Go github.com/imgproxy/imgproxy/v3: >= 3.3.0, < 4.0.16 → fixed in 4.0.16
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(' 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.
Related
Weakness · CWE (1)
- CWE-400 Uncontrolled Resource Consumption weakness