Open-Source Security Research

Ligolo-ng v0.8.3

Kuzushi Security's automated scan of Ligolo-ng, a widely-used offensive network tunneling tool, uncovered 27 true positive findings across 10 scanner strategies — including critical race conditions that crash the agent process, absent mutual authentication between proxy and agent enabling session hijacking, and default credentials on the Web API — demonstrating fundamental security gaps in a tool deployed across red team operations worldwide.

Scanned Apr 7, 2026·9k+ lines·10 scanners·~88m·Source →
71
Verified Findings
18
Critical + High
60
Threats Modeled
No mutual authentication between proxy and agent — the TLS channel provides encryption but any host that can reach the proxy listener port is implicitly trusted as a legitimate agent, enabling session hijacking, traffic interception, and remote agent termination.
Top Structural Weakness

Key Findings

71 findings across 22 files using 10 scannersscannerOne analysis engine inside Kuzushi. A single scan runs many scanners in parallel (Semgrep, CodeQL, AI Threat Hunting, etc.) and merges results by fingerprint.. 27 confirmed true positives (38% precision).

highseverityHow bad a single finding is, on a 4-point scale (critical / high / medium / low). A property of one code-level finding — not the threat model.AI Threat Hunting

Concurrent Map Data Race Crashes Agent via Unsynchronized Global State

Concurrent data race on unprotected global maps and counters: listenerConntrack, listenerMap, connTrackID, and listenerID are package-level variables accessed from multiple goroutines (every yamux stream dispatches a new go agent.HandleConn() goroutine at cmd/agent/main.go:252 and :352) with zero synchronization. The ListenAndServe goroutine (line 258) writes connTrackID++ and listenerConntrack[connTrackID]=conn while another HandleConn goroutine may simultaneously read listenerConntrack[sockRequest.SockID] (line 347) or read/write listenerMap (lines 208, 249, 278). In Go, concurrent map read+write triggers a fatal runtime panic; a race between two ListenerRequestPackets from the proxy will also corrupt listenerID++ (line 295) non-atomically. An attacker controlling the proxy can reliably trigger this by issuing two simultaneous listener_add or listener_stop commands, crashing the agent.

highAgentic Review

Concurrent Map Race on Agent Listener Globals Crashes Agent

Global maps (listenerConntrack, listenerMap) and counters (connTrackID, listenerID) are written and read concurrently from multiple goroutines without synchronization, causing a data race that can crash the agent process.

highRace-Condition Detector

Concurrent Map Access on AgentList Crashes Proxy Server

Global map `AgentList` iterated and read by multiple Gin HTTP handlers without holding `AgentListMutex`, while `RegisterAgent` writes to it under the mutex from a separate goroutine. Gin serves each HTTP request in its own goroutine, so concurrent map access is guaranteed. Affected handlers: GET /listeners (line 317), GET /agents (line 393), DELETE /listeners (line 345), POST /listeners (line 366), DELETE /tunnel/:id (line 403), POST /tunnel/:id (line 508). Contrast: POST /relay/:id (line 433), DELETE /relay/:id (line 462), and GET /chains (line 479) do correctly acquire AgentListMutex. In Go, a concurrent map read+write is undefined behavior and triggers a `runtime: concurrent map read and map write` fatal panic at runtime. [resource: var AgentList map[int]*controller.LigoloAgent (cmd/proxy/app/app.go:47)]

highAI Threat Hunting

DELETE /listeners Omits Stop(), Leaving Agent Port Open and Goroutine Leaked

DELETE /listeners removes the listener from API tracking but never calls listener.Stop(), leaving the listener actively running on the agent side — enabling stealth persistent port forwarders

highAI Threat Hunting

Data Race on AgentList Map Causes Fatal Proxy Crash

Data race on global AgentList map: multiple API handlers read and write AgentList without holding AgentListMutex, while RegisterAgent() (app.go:73) always locks it. Concurrent agent connect/disconnect events and simultaneous API requests will trigger Go's map concurrent-access panic (fatal error: concurrent map read and map write). Exploitable by an authenticated client making rapid API calls (e.g., GET /agents, GET /listeners, POST /listeners, DELETE /tunnel/:id) while an agent is connecting or being recovered. Affected handlers: GET /listeners (line 316), DELETE /listeners (lines 345, 349), POST /listeners (lines 366, 370), GET /agents (line 393), DELETE /tunnel/:id (lines 403, 407), POST /tunnel/:id (~line 504). Only POST /relay/:id and DELETE /relay/:id correctly lock the mutex.

Want this level of analysis on your codebase?

Connect your GitHub and get continuous scanning, AI triage, threat modeling, and expert verification — all managed.