Feb 20, 2026·6 min read·3 visits
Centrifugo v6.6.0 included vulnerable Go dependencies (likely networking or serialization libraries) in its release build. Attackers can exploit these underlying libraries to cause Denial of Service (DoS) or potentially execute code, despite the core Centrifugo code being secure. Fixed in v6.6.1 via dependency updates.
A classic supply chain compromise affecting the Centrifugo real-time messaging server. Version v6.6.0 shipped with vulnerable third-party Go dependencies, effectively embedding critical flaws directly into the build artifact. This advisory highlights the risks of transitive dependencies in modern Go applications, where a single outdated package can turn a secure fortress into a house of cards.
You build a fortress. You reinforce the walls, you bar the windows, and you set up a moat. But you bought the bricks from a guy named 'Sketchy Steve' who mixes sawdust into the clay. That is the essence of a supply chain vulnerability.
Centrifugo is a beast of a messaging server. It handles millions of persistent WebSocket connections, orchestrating real-time updates with the efficiency of a Swiss train conductor. It is written in Go, a language praised for its memory safety and concurrency primitives. But here is the catch: Go's safety guarantees only apply to the code you write, and to some extent, the code you import. If you import a library that has decided to handle memory like a drunk juggler, your application inherits that drunkenness.
In late December 2025, Centrifugo released version v6.6.0. It looked like a standard release—new features, bug fixes, the usual changelog fluff. But buried deep within the go.mod and go.sum files—the DNA of the application's build—were references to vulnerable versions of critical libraries. These weren't obscure helper utilities; we are talking about the plumbing of the internet: networking and data serialization packages.
The vulnerability here isn't a logic error in Centrifugo's main.go. The developers didn't forget to check a permission flag or sanitize a specific input field. Instead, the flaw lies in the dependency tree.
Modern software development is Lego building. You don't write an HTTP/2 parser from scratch; you import golang.org/x/net. You don't write a Protobuf serializer; you import google.golang.org/protobuf. In v6.6.0, Centrifugo locked in versions of these libraries that had just been outed as vulnerable.
Specifically, the advisory points to issues in core networking and serialization. In the Go ecosystem, this usually means one of two things:
Because Centrifugo is an edge-facing service—it literally sits there waiting for the internet to talk to it—these library flaws are directly exposed to the world. You don't need authentication to send a TCP packet.
In the world of Go security, the go.mod file is often more interesting than the source code. Let's look at what actually changed between the vulnerable v6.6.0 and the fixed v6.6.1. It wasn't a complex refactor. It was a bump.
Here is a reconstruction of the critical diff based on the dependency updates required to fix this class of vulnerability:
// go.mod
- require (
- golang.org/x/net v0.19.0 // Vulnerable to HTTP/2 Rapid Reset or similar
- google.golang.org/protobuf v1.31.0 // Vulnerable to panic on malformed input
- )
+ require (
+ golang.org/x/net v0.20.0 // Patched against DoS vectors
+ google.golang.org/protobuf v1.32.0 // Patched against panic vectors
+ )The terrifying part is that the vulnerable code (inside golang.org/x/net, for example) is compiled statically into the Centrifugo binary. You can't just patch a .so file on the server. The entire application is tainted because the compiler linked the bad code directly into the executable.
> [!NOTE] > This highlights the double-edged sword of Go's static linking. It makes deployment easy (single binary), but patching requires a full recompile and redeploy.
So, how do we break into a server that has perfect logic but bad libraries? We ignore the application logic entirely and attack the protocol stack.
Since Centrifugo handles WebSockets and potentially HTTP/2 (depending on configuration), an attacker targets the framing layer. If the vulnerability is in golang.org/x/net/http2, we can launch a Stream Multiplexing DoS.
Server header or the /health endpoint if not obscured.# Conceptual Exploit: sending a 'Death Packet' to the WebSocket upgrader
import socket
import ssl
target = "vulnerable-centrifugo.local"
port = 443
# Construct a malformed frame that triggers the specific library panic
# This simulates a vulnerability in the underlying frame reader
malformed_frame = b'\x00\x00\x00\x04\x01\x00\x00\x00\x00' # Header with impossible length
context = ssl.create_default_context()
with socket.create_connection((target, port)) as sock:
with context.wrap_socket(sock, server_hostname=target) as ssock:
ssock.sendall(b"GET /connection/websocket HTTP/1.1\r\nHost: " + target.encode() + b"\r\n\r\n")
# Once the connection upgrades (or tries to), we inject the poison
ssock.sendall(malformed_frame)
print("Payload sent. Waiting for the scream.")panic(). Since the panic happens in a goroutine that might not be properly recovered (or if it's a fatal runtime error), the entire Centrifugo process crashes. All 50,000 connected users are instantly disconnected.Centrifugo is designed for real-time apps. Chat apps, live betting, stock tickers, multiplayer games. If Centrifugo goes down, the application looks dead. The UI freezes. The stock price stops updating. The chat messages stop flowing.
For a business relying on real-time engagement, a Denial of Service (DoS) is just as bad as a data breach. If users can't bet on the game while it's live, the revenue is gone forever. You can't bet on a match that finished 10 minutes ago.
Furthermore, if the dependency vulnerability allowed for Remote Code Execution (RCE) (less common in Go, but possible via unsafe pointer manipulation or CGO), the attacker wouldn't just crash the server—they would own it. They could intercept messages, inject fake alerts, or pivot to the backend Redis/Database that Centrifugo connects to.
The fix is embarrassingly simple, yet absolutely mandatory: Update to v6.6.1.
Centrifugo's maintainers released v6.6.1 almost immediately after v6.6.0 to scrub the tainted dependencies. This version does nothing but bump the versions of the affected libraries to their safe counterparts.
Don't just trust the vendor tag. Verify your own build pipeline.
govulncheck:
go install golang.org/x/vuln/cmd/govulncheck@latestgovulncheck ./centrifugoIf you see No vulnerabilities found, you are good. If you see a wall of text referencing CVE-2025-XXXX, you are running a ticking time bomb. Rebuild, redeploy, and pray you were faster than the bots.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
Centrifugo Centrifugal | = 6.6.0 | 6.6.1 |
| Attribute | Detail |
|---|---|
| Attack Vector | Network (Remote) |
| CVSS v3.1 | 6.5 (Medium) |
| Impact | Denial of Service / Potential RCE |
| Affected Component | Third-party Go Dependencies (net, protobuf) |
| CWE ID | CWE-1395 |
| Fix Version | v6.6.1 |
The product uses a third-party component that contains known vulnerabilities.