critical · 9.8 Patched

imgproxy has integer overflow in imgproxy ICO loader that causes denial of service and may permit remote code execution

GHSA-hff9-5pqw-6w9f · published 30 Oct 2026

How serious is it

  • Severity: critical, CVSS score 9.8 out of 10.
  • No exploit prediction (EPSS) score yet.
  • Not on the CISA list of exploited vulnerabilities.
  • No public exploit in Exploit-DB.

Is your app affected by GHSA-hff9-5pqw-6w9f?

Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.

Who is affected

  • github.com/imgproxy/imgproxy/v3 (Go) >= 4.0.0, < 4.0.16
  • github.com/imgproxy/imgproxy/v2 (Go) >= 4.0.0, < 4.0.16
  • github.com/imgproxy/imgproxy (Go) >= 4.0.0, < 4.0.16

How to check

  1. Run go list -m github.com/imgproxy/imgproxy/v3 in your project to see the installed version, including copies pulled in by other packages.
  2. Run go list -m github.com/imgproxy/imgproxy/v2 in your project to see the installed version, including copies pulled in by other packages.
  3. Run go list -m github.com/imgproxy/imgproxy in your project to see the installed version, including copies pulled in by other packages.
  4. Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.

How to fix

Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
  1. On >= 4.0.0, < 4.0.16: Upgrade github.com/imgproxy/imgproxy/v3 to 4.0.16 or later, commit the lockfile and redeploy.
  2. On >= 4.0.0, < 4.0.16: Upgrade github.com/imgproxy/imgproxy/v2 to 4.0.16 or later, commit the lockfile and redeploy.
  3. On >= 4.0.0, < 4.0.16: Upgrade github.com/imgproxy/imgproxy to 4.0.16 or later, commit the lockfile and redeploy.
  4. If a vulnerable version was live, check your logs and rotate the secrets that server could read.

The advisory

## Summary The ICO loader allocates `data_size + BMP_FILE_HEADER_LEN` bytes after reading a 32-bit attacker-controlled `data_size`. For `data_size > UINT32_MAX - BMP_FILE_HEADER_LEN`, the addition wraps before allocation. imgproxy then writes the ICO prefix and reads up to the original declared size starting 14 bytes into the undersized allocation. A network client can turn this heap overflow into remote denial of service or remote code execution. ## Technical details The vulnerable path is in [`vips/icoload.c` at commit `f4fedbb`](https://github.com/imgproxy/imgproxy/blob/f4fedbb5c7f6684e7a8e0a9bb7e666773f3c40c0/vips/icoload.c#L154-L164): ```c uint32_t data_size = GUINT32_FROM_LE(largest_image_header.data_size); VipsPel *data = (VipsPel *) VIPS_MALLOC(NULL, data_size + BMP_FILE_HEADER_LEN); void *actual_data = data + BMP_FILE_HEADER_LEN; if (vips_foreign_load_read_full(ico->source, actual_data, data_size) <= 0) { vips_error("vips_foreign_load_ico_header", "unable to read ICO image data from the source"); return -1; } ``` The crafted directory entry contains: ```text data_size = 0xfffffff5 (4294967285) data_offset = 22 BMP header size = 14 32-bit result = (0xfffffff5 + 14) mod 2^32 = 3 ``` The allocation is therefore three bytes. `actual_data` points 14 bytes after the allocation base. The fixture contains 64 bytes after the ICO header, so the source callback copies those 64 bytes to an invalid destination before it can report that the declared multi-gigabyte payload is incomplete. The complete source-to-sink path is: 1. Attacker-controlled bytes begin with the ICO magic `00 00 01 00`. 2. imgproxy identifies the source as ICO and dispatches it to `vips_icoload_source_go`. 3. `vips_foreign_load_ico_header` reads the attacker-controlled `data_size`. 4. The 32-bit addition wraps, and `VIPS_MALLOC` receives the value three. 5. `vips_foreign_load_read_full` passes the original `data_size` to the Go source callback. 6. The callback writes the available source bytes through the invalid pointer, corrupting the process heap. ## Impact A crafted image can terminate the imgproxy process handling it or potentially lead to remote code execution due to heap corruption.

Check your whole app

Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.

References

Merged from GitHub Advisory Database, OSV. Last updated 31 Oct 2026. All vulnerabilities · RSS · JSON