Big Brother Runs XMRig - CVE 2026-25643

It all began with a curiosity about how surveillance cameras work and, more importantly, what they are actually capable of detecting. I started with a small project that eventually became a personal ALPR system for collecting statistics and generating alerts, with privacy as one of the core considerations. As usually happens when I discover a new subject, I fell down a rabbit hole. I started looking into surveillance cameras in greater detail: the protocols they use, how video streams are transported, how NVRs are deployed, and how these systems are typically exposed on a network.

I didn’t start this investigation knowing about an RCE, and I wasn’t looking for CVEs. I was trying to understand a strange stream definition I had encountered while looking at a running installation. The issue had in fact already been reported and was later assigned CVE-2026-25643, affecting Frigate versions up to 0.16.3 and fixed in 0.16.4. The published advisory describes it as a critical RCE in the Frigate/go2rtc integration.

I didn’t discover a new vulnerability. But independently finding the same command execution path while investigating an actual deployment was still interesting enough to document.

NVR and DVR #

Before getting into the vulnerability itself, it is useful to understand the basic architecture behind modern surveillance systems. At a high level, a DVR (Digital Video Recorder) and an NVR (Network Video Recorder) both serve the same general purpose, receiving video from cameras and recording it for later viewing. The main distinction is where the video is processed. Traditional DVRs are generally designed around analog cameras, with video transported to the recorder over dedicated coaxial connections. The DVR is responsible for digitizing and processing those signals before storing them. NVRs, are designed around IP cameras. The cameras themselves encode the video and expose it as network streams, while the NVR connects to those streams over the network and handles recording, management, motion detection, object detection, and other processing.

This distinction makes an NVR much closer to a conventional networked computer than a traditional DVR. An NVR typically runs an operating system, exposes HTTP-based management interfaces, communicates with multiple network services, stores credentials and camera configurations, and may provide additional functionality such as AI-based object detection. Consequently, compromising an NVR can provide considerably more than access to recorded video. Depending on its configuration and privileges, it can also provide access to the underlying host and the network to which it is connected.

Protocols #

IP cameras rely on a collection of network protocols and standards to make video available to other devices. These protocols do not all serve the same purpose.

ONVIF (Open Network Video Interface Forum) defines standardized interfaces that allow compatible surveillance devices to discover one another and exchange information such as device capabilities, media profiles, controls, and configuration. It is primarily an interoperability standard rather than a video codec or transport protocol.

For the actual video, one of the most common protocols encountered in surveillance environments is RTSP (Real Time Streaming Protocol). RTSP provides a control layer for establishing and managing media streams, while the actual media is commonly transported using RTP. A camera may therefore expose an RTSP URL that an NVR can connect to and continuously pull frames from. Other systems may use protocols such as HLS (HTTP Live Streaming), which delivers media through HTTP and is particularly common when video needs to be consumed by web browsers or other HTTP-based clients.

This creates an architecture in which an IP camera is effectively a network service providing one or more media streams, while the NVR acts as a client consuming those streams. A typical setup might look like an IP Camera exposing an RTSP stream that is consumed by an NVR, which stores snapshots and short videos when a person is detected, then it exposes the collection of videos, snapshots, and a live feed in the web interface.

The details vary considerably between vendors and software, but the important security implication is that every additional protocol and service introduces another component into the attack surface. Camera discovery, stream transport, web interfaces, APIs, authentication mechanisms, and the software responsible for processing those streams can all become relevant when analyzing the security of an NVR deployment.

Frigate #

For most users, deploying a surveillance system is relatively straightforward. Purchase a camera, mount it, connect it to the network, and configure an NVR to record and process the resulting streams. Personal and self-hosted installations increasingly rely on open-source NVR software, with Frigate being one of the more popular choices.

Frigate is an open-source NVR built around real-time AI-based object detection. It integrates with camera streams through protocols such as RTSP and uses go2rtc as its streaming component for handling and restreaming media.

go2rtc #

Rather than having the NVR directly handle every camera protocol and streaming format, go2rtc acts as a gateway between the cameras and anything consuming the streams. It can consume an rtsp stream and make it available through protocols and formats like webRTC and HLS. Frigate can reference the camera by name, while go2rtc handles the actual connection and conversion required by consumers. So an IP Camera exposes an RTSP stream, which is handled by go2rtc, which is then referenced and consumed by Frigate, which can be configured to detect people, objects, etc. and record videos on demand.

Common Problems #

However, while deploying and testing such a system can be straightforward, securing it properly is considerably less so. A common problem is exposing services that were intended to be reachable only from the local network or from trusted components.

During testing, I encountered exactly this situation. Frigate’s primary authenticated interface was exposed on TCP port 8971, as expected. However, the same installation also exposed Frigate’s port 5000, which is intended for internal use and does not provide the same authentication. Additionally, the go2rtc web interface was directly accessible on TCP port 1984.

Unusual Streams #

While inspecting the stream configuration exposed through Frigate’s /api/config endpoint, I noticed an unusual stream definition that did not correspond to a normal camera source (e.g. rtsp://). Instead, its configuration contained a large Base64 encoded blob compressed using gzip.

The stream was registered as a debug stream and, more importantly, its source made use of go2rtc’s exec functionality. The configured command formed a shell pipeline that decoded the Base64 data, decompressed it using zcat, and passed the resulting content to the shell for execution.


"maliciousstream":{"producers":[{"url":"exec:/bin/bash -c 'base64 -d {PAYLOAD} | zcat|sh'"}],"consumers":null}}

The payload #

Decoding the payload revealed something considerably more interesting: it was a Linux-based Monero cryptocurrency-mining payload.

The payload begins by fingerprinting the host and collecting information about the environment. Among other things, it determines the CPU architecture, number of CPUs, NUMA topology, available memory, CPU model, hostname, and the locally listening go2rtc port. This information is subsequently used to determine an appropriate mining configuration and thread count.

The payload contains a hard-coded Monero wallet address and mining-pool configuration. It also implements architecture- and distribution-specific deployment logic: on Alpine and Debian-based systems it installs the dependencies required by the miner, while on x86-64 systems it retrieves a precompiled XMRig binary. On other architectures, it instead obtains the XMRig source and builds it locally.

The resulting binary is copied to an inconspicuous $DIR/.trace path and marked executable. Before starting the miner, the payload checks whether an existing .trace process is already running, presumably to avoid spawning multiple mining instances. It then launches XMRig in the background with parameters controlling CPU priority, thread allocation, keepalive behavior, donation settings, logging, and the selected mining pool.

The payload also attempts to protect its configuration from modification. It locates the go2rtc YAML configuration and applies the Linux immutable-file attribute using chattr +i. This prevents ordinary writes to the file and provides a basic mechanism for maintaining the attacker’s configuration.

Finally, the script establishes a monitoring loop that periodically queries the local go2rtc API. Every five seconds, it examines recent log data, extracts a src= value, and hashes it using SHA-256. If the resulting hash matches a hard-coded value embedded in the payload, the script temporarily removes the immutable attribute, deletes the go2rtc logs, waits for a fixed interval, and then restores the immutable attribute.

Taken together, these behaviors show that the payload was not simply a cryptocurrency miner, but it also contained host reconnaissance, architecture-aware deployment, process management, configuration tampering, anti-modification measures, and a mechanism for selectively removing evidence from the go2rtc environment.

Abusing Legitimate Functionality #

What makes this attack particularly interesting is that it does not rely on introducing an obviously malicious configuration directive. Instead, it abuses functionality that already exists for legitimate purposes. In a legitimate deployment, exec can be used to invoke an external process as part of a media source. It becomes problematic when an attacker is able to influence a configuration containing such a directive. Once the configuration is consumed by the streaming component, the command executes with the privileges available to the Frigate/go2rtc process.

The attack can be understood like such: An exposed service, which allows unauthenticated access, can be configured to save a malicious stream that will make use of the exec directive, which may be used to execute code remotely.

Final Words #

It is important to separate the vulnerability from the payload used in this incident. The exec directive is legitimate functionality. Its presence alone does not constitute malicious behavior. The security issue arises when an attacker can reach a configuration interface that should be protected and use that access to supply attacker-controlled configuration to a component capable of executing commands.

In other words, the cryptocurrency miner is the payload, not the vulnerability. The vulnerable configuration path provides the attacker with a route to command execution, while the miner is simply what the observed attacker chose to execute once that capability was available.

This distinction is important because replacing the mining payload with a different command would leave the underlying attack primitive unchanged. The same execution path could potentially be used to run other attacker-controlled commands with the privileges of the affected service.