VYPR
High severityNVD Advisory· Published Feb 19, 2026· Updated Feb 19, 2026

emp3r0r Affected by Concurrent Map Access DoS (panic/crash)

CVE-2026-26201

Description

emp3r0r is a C2 designed by Linux users for Linux environments. Prior to version 3.21.2, multiple shared maps are accessed without consistent synchronization across goroutines. Under concurrent activity, Go runtime can trigger fatal error: concurrent map read and map write, causing C2 process crash (availability loss). Version 3.21.2 fixes this issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

emp3r0r C2 before v3.21.2 crashes on concurrent map access due to missing synchronization, leading to availability loss.

CVE-2026-26201 is a denial-of-service vulnerability in emp3r0r, a Linux-focused post-exploitation C2 framework [2]. The root cause is that multiple shared maps in the codebase are accessed without consistent synchronization across goroutines. Under concurrent map read and map write, which forcibly terminates the C2 process [1][3].

No authentication or special network position is required to exploit this race condition is required beyond the ability to trigger concurrent operations that interact with the unsynchronized maps. The vulnerable maps include, but are not limited to, live.AgentControlMap and AgentFileTransferSessions, both of which were originally implemented as standard Go maps protected by a mutex in some places but not others [1]. Under concurrent activity—because the crash is triggered by the Go runtime itself, any concurrent workload (or even sequential) access pattern that hits the race condition will cause a C2 process crash.

The primary impact is a complete loss of availability of the C2 server. An attacker who can cause concurrent agent check-ins, file transfers, or other map-modifying activities can repeatedly crash the control server, disrupting red team operations or command-and-control infrastructure [1][3].

The vulnerability is fixed in version 3.21.2 [4]. The patch replaces map-based concurrency with sync.Map, providing built-in safe concurrent access without requiring external mutexes [1]. Users are advised to upgrade immediately. No workaround beyond the patch is available [3].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/jm33-m0/emp3r0r/coreGo
< 0.0.0-20260212232424-ea4d074f081d0.0.0-20260212232424-ea4d074f081d

Affected products

1
  • jm33-m0/emp3r0rv5
    Range: < 3.21.2

Patches

1
ea4d074f081d

fix: replace map-based concurrency with sync.Map for improved thread safety and performance.

https://github.com/jm33-m0/emp3r0rjm33-m0Feb 12, 2026via ghsa
36 files changed · +496 457
  • core/internal/agent/base/c2transport/connect_test.go+3 4 modified
    @@ -16,6 +16,7 @@ import (
     	"os"
     	"path/filepath"
     	"strings"
    +	"sync"
     	"testing"
     	"time"
     
    @@ -335,11 +336,9 @@ func TestDuplicatedCheckin(t *testing.T) {
     		CAPEM:  string(caCertData),
     	}
     
    -	// Reset live maps with proper locking
    -	live.AgentControlMapMutex.Lock()
    -	live.AgentControlMap = make(map[*def.Emp3r0rAgent]*live.AgentControl)
    +	// Reset live maps
    +	live.AgentControlMap = sync.Map{}
     	live.AgentList = make([]*def.Emp3r0rAgent, 0)
    -	live.AgentControlMapMutex.Unlock()
     
     	// Start Real C2 Server
     	go server.StartC2AgentTLSServer()
    
  • core/internal/agent/base/c2transport/file_transfer.go+6 8 modified
    @@ -221,11 +221,10 @@ func SendFile2CC(filepath string, offset int64, token string) (err error) {
     	return
     }
     
    -var (
    -	// AgentFileTransferSessions stores active file transfer sessions between agents
    -	AgentFileTransferSessions = make(map[string]context.CancelFunc)
    -	sessionsMutex             sync.Mutex
    +// AgentFileTransferSessions stores active file transfer sessions between agents
    +var AgentFileTransferSessions sync.Map
     
    +var (
     	// FileServer switch
     	FileServerCtx    context.Context
     	FileServerCancel context.CancelFunc
    @@ -358,13 +357,12 @@ func FetchFileKCP(address, filepath, path, checksum string) (err error) {
     // CancelFileTransfer cancels an ongoing file transfer session
     func CancelFileTransfer(clientAddr, filepath string) {
     	sessionID := fmt.Sprintf("%s:%s", clientAddr, filepath)
    -	sessionsMutex.Lock()
    -	defer sessionsMutex.Unlock()
     
    -	if cancel, exists := AgentFileTransferSessions[sessionID]; exists {
    +	if val, exists := AgentFileTransferSessions.Load(sessionID); exists {
    +		cancel := val.(context.CancelFunc)
     		cancel()
     		logging.Printf("File transfer session for %s canceled", sessionID)
    -		delete(AgentFileTransferSessions, sessionID)
    +		AgentFileTransferSessions.Delete(sessionID)
     	} else {
     		logging.Printf("No active file transfer session for %s", sessionID)
     	}
    
  • core/internal/agent/base/c2transport/lifecycle_test.go+11 18 modified
    @@ -9,6 +9,7 @@ import (
     	"os"
     	"path/filepath"
     	"strings"
    +	"sync"
     	"testing"
     	"time"
     
    @@ -78,11 +79,9 @@ func TestFullAgentLifecycle(t *testing.T) {
     		CAPEM:  string(caCertData),
     	}
     
    -	// Reset live maps with proper locking
    -	live.AgentControlMapMutex.Lock()
    -	live.AgentControlMap = make(map[*def.Emp3r0rAgent]*live.AgentControl)
    +	// Reset live maps
    +	live.AgentControlMap = sync.Map{}
     	live.AgentList = make([]*def.Emp3r0rAgent, 0)
    -	live.AgentControlMapMutex.Unlock()
     
     	// Initialize agent database for tracking BEFORE starting server
     	dbPath := filepath.Join(tmpDir, "agents.db")
    @@ -291,7 +290,6 @@ func TestFullAgentLifecycle(t *testing.T) {
     
     	// Verify pending request matches
     	var newKey string
    -	var ok bool
     	timeout := time.After(5 * time.Second)
     	ticker := time.NewTicker(100 * time.Millisecond)
     
    @@ -300,10 +298,8 @@ func TestFullAgentLifecycle(t *testing.T) {
     		case <-timeout:
     			t.Fatal("Timed out waiting for PendingKeyRotations")
     		case <-ticker.C:
    -			live.PendingKeyRotationsMutex.RLock()
    -			newKey, ok = live.PendingKeyRotations[agentUUID]
    -			live.PendingKeyRotationsMutex.RUnlock()
    -			if ok {
    +			if val, exists := live.PendingKeyRotations.Load(agentUUID); exists {
    +				newKey = val.(string)
     				goto PendingFound
     			}
     		}
    @@ -314,19 +310,17 @@ PendingFound:
     	}
     
     	// Approve key rotation (Simulate operator command logic)
    -	live.PendingKeyRotationsMutex.Lock()
    -
     	// Update in-memory map
    -	live.AgentControlMapMutex.Lock()
     	foundAgent := false
    -	for a := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.UUID == agentUUID {
     			a.PublicKey = newKey
     			foundAgent = true
    -			break
    +			return false // stop iteration
     		}
    -	}
    -	live.AgentControlMapMutex.Unlock()
    +		return true
    +	})
     
     	// If agent disconnected, it won't be in map, so we update DB
     	if !foundAgent {
    @@ -340,8 +334,7 @@ PendingFound:
     	}
     
     	// Clear pending
    -	delete(live.PendingKeyRotations, agentUUID)
    -	live.PendingKeyRotationsMutex.Unlock()
    +	live.PendingKeyRotations.Delete(agentUUID)
     	t.Log("✓ Key rotation approved manually")
     
     	// Check in again with new key (should succeed now)
    
  • core/internal/agent/handler/c2cmd_runners.go+13 13 modified
    @@ -130,13 +130,12 @@ func runBring2CC(cmd *cobra.Command, args []string) {
     		c2transport.NotifyC2(cmd, "Error: We don't have any internet to share\n")
     		return
     	}
    -	modules.ReverseConnsMutex.Lock()
    -	for p, cancelfunc := range modules.ReverseConns {
    -		if addr == p {
    -			cancelfunc()
    +	modules.ReverseConns.Range(func(p, cancelfunc interface{}) bool {
    +		if addr == p.(string) {
    +			cancelfunc.(context.CancelFunc)()
     		}
    -	}
    -	modules.ReverseConnsMutex.Unlock()
    +		return true
    +	})
     	targetAddrWithPort := fmt.Sprintf("%s:%s", addr, common.RuntimeConfig.Bring2CCReverseProxyPort)
     	ctx, cancel := context.WithCancel(context.Background())
     	kcpListenPort := fmt.Sprintf("%d", util.RandInt(10000, 60000))
    @@ -173,7 +172,7 @@ func runBring2CC(cmd *cobra.Command, args []string) {
     			return
     		}
     	}
    -	err = transport.SSHReverseProxyClient(targetAddrWithPort, common.RuntimeConfig.Password, proxyPort, &modules.ReverseConns, modules.ReverseConnsMutex, def.ProxyServer, ctx, cancel)
    +	err = transport.SSHReverseProxyClient(targetAddrWithPort, common.RuntimeConfig.Password, proxyPort, &modules.ReverseConns, def.ProxyServer, ctx, cancel)
     	if err != nil {
     		c2transport.NotifyC2(cmd, "%v\n", err)
     		return
    @@ -247,10 +246,9 @@ func runPortFwd(cmd *cobra.Command, args []string) {
     	errChan := make(chan error)
     	switch operation {
     	case "stop":
    -		modules.PortFwdsMutex.Lock()
    -		pf, exist := modules.PortFwds[sessionID]
    -		modules.PortFwdsMutex.Unlock()
    +		val, exist := modules.PortFwds.Load(sessionID)
     		if exist {
    +			pf := val.(*modules.PortFwdSession)
     			pf.Cancel()
     			c2transport.NotifyC2(cmd, "Warning: port mapping %s stopped\n", pf.Addr)
     			return
    @@ -295,11 +293,13 @@ func runDeletePortFwd(cmd *cobra.Command, args []string) {
     	if id == "" {
     		return
     	}
    -	for sessionID, session := range modules.PortFwds {
    -		if sessionID == id {
    +	modules.PortFwds.Range(func(sessionID, value interface{}) bool {
    +		if sessionID.(string) == id {
    +			session := value.(*modules.PortFwdSession)
     			session.Cancel()
     		}
    -	}
    +		return true
    +	})
     	c2transport.NotifyC2(cmd, "")
     }
     
    
  • core/internal/agent/modules/proxychain.go+1 4 modified
    @@ -23,10 +23,7 @@ import (
     )
     
     // ReverseConns record ssh reverse proxy sessions
    -var (
    -	ReverseConns      = make(map[string]context.CancelFunc)
    -	ReverseConnsMutex = &sync.Mutex{}
    -)
    +var ReverseConns sync.Map
     
     // getRollingTag generates a time-based token (TOTP style)
     // It creates a unique 4-byte signature for the given time slot.
    
  • core/internal/agent/modules/proxy.go+4 13 modified
    @@ -29,13 +29,8 @@ type PortFwdSession struct {
     	Cancel context.CancelFunc
     }
     
    -var (
    -	// PortFwds manage port mappings
    -	PortFwds = make(map[string]*PortFwdSession)
    -
    -	// PortFwdsMutex lock map
    -	PortFwdsMutex = &sync.Mutex{}
    -)
    +// PortFwds manage port mappings
    +var PortFwds sync.Map
     
     // Socks5Proxy sock5 proxy server on agent, listening on addr
     // op: on/off
    @@ -137,9 +132,7 @@ func PortFwd(addr, sessionID, protocol string, reverse bool, timeout int) (err e
     			conn.Close()
     		}
     
    -		PortFwdsMutex.Lock()
    -		delete(PortFwds, sessionID)
    -		PortFwdsMutex.Unlock()
    +		PortFwds.Delete(sessionID)
     		logging.Printf("PortFwd stopped: %s (%s)", addr, sessionID)
     	}()
     
    @@ -148,9 +141,7 @@ func PortFwd(addr, sessionID, protocol string, reverse bool, timeout int) (err e
     	session.Conn = conn
     	session.Ctx = ctx
     	session.Cancel = cancel
    -	PortFwdsMutex.Lock()
    -	PortFwds[sessionID] = &session
    -	PortFwdsMutex.Unlock()
    +	PortFwds.Store(sessionID, &session)
     
     	// check if h2conn is disconnected,
     	// if yes, kill all goroutines and cleanup
    
  • core/internal/agent/modules/ssh_harvester_amd64_linux.go+3 8 modified
    @@ -26,8 +26,7 @@ var (
     	SshHarvesterRunning bool
     
     	// record traced sshd sessions
    -	traced_pids     = make(map[int]bool)
    -	traced_pids_mut = &sync.RWMutex{}
    +	traced_pids = sync.Map{}
     
     	// provide a way to stop the harvester
     	SshHarvesterCtx    context.Context
    @@ -69,11 +68,9 @@ func SshHarvester(cmd *cobra.Command, code_pattern []byte, reg_name string) (err
     			for _, child := range children_pids {
     				child_pid, err := strconv.Atoi(child)
     				if err == nil {
    -					traced_pids_mut.RLock()
    -					if !traced_pids[child_pid] {
    +					if _, ok := traced_pids.Load(child_pid); !ok {
     						go sshd_harvester(child_pid, cmd, code_pattern, reg_name)
     					}
    -					traced_pids_mut.RUnlock()
     				}
     			}
     		}
    @@ -95,9 +92,7 @@ func sshd_harvester(pid int, cmd *cobra.Command, code_pattern []byte, reg_name s
     	defer c2transport.NotifyC2(cmd, "SSH harvester for sshd session %d done", pid)
     
     	// remember pid
    -	traced_pids_mut.Lock()
    -	traced_pids[pid] = true
    -	traced_pids_mut.Unlock()
    +	traced_pids.Store(pid, true)
     
     	// passwords
     	passwords := make([]string, 1)
    
  • core/internal/cc/base/agents/disconnect.go+14 8 modified
    @@ -1,6 +1,8 @@
     package agents
     
     import (
    +	"sync"
    +
     	"github.com/jm33-m0/emp3r0r/core/internal/def"
     	"github.com/jm33-m0/emp3r0r/core/internal/live"
     	"github.com/jm33-m0/emp3r0r/core/lib/logging"
    @@ -9,19 +11,22 @@ import (
     // DisconnectAllAgents closes all agent connections
     // This should be called when the last operator disconnects
     func DisconnectAllAgents() {
    -	live.AgentControlMapMutex.Lock()
    -	defer live.AgentControlMapMutex.Unlock()
    -
    -	count := len(live.AgentControlMap)
    +	count := 0
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		count++
    +		return true
    +	})
     	if count == 0 {
     		return
     	}
     
     	logging.Infof("Disconnecting all %d agent(s) due to operator exit", count)
     
    -	for agent, ctrl := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		agent := key.(*def.Emp3r0rAgent)
    +		ctrl := value.(*live.AgentControl)
     		if ctrl == nil {
    -			continue
    +			return true
     		}
     
     		// Close the connection
    @@ -35,9 +40,10 @@ func DisconnectAllAgents() {
     		if ctrl.Cancel != nil {
     			ctrl.Cancel()
     		}
    -	}
    +		return true
    +	})
     
     	// Clear the map
    -	live.AgentControlMap = make(map[*def.Emp3r0rAgent]*live.AgentControl)
    +	live.AgentControlMap = sync.Map{}
     	logging.Infof("All agents disconnected")
     }
    
  • core/internal/cc/base/agents/label.go+14 14 modified
    @@ -29,18 +29,15 @@ func PersistLabeledAgentsToFile() {
     	)
     	if util.IsExist(AgentsJSON) {
     		data, readErr := os.ReadFile(AgentsJSON)
    -		if readErr != nil {
    -			logging.Warningf("Reading labeled agents: %v", readErr)
    -		}
    -		readErr = json.Unmarshal(data, &old)
    -		if readErr != nil {
    -			logging.Warningf("Reading labeled agents: %v", readErr)
    +		if readErr == nil {
    +			_ = json.Unmarshal(data, &old)
     		}
     	}
    -outter:
    -	for t, c := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(tag, control interface{}) bool {
    +		t := tag.(*def.Emp3r0rAgent)
    +		c := control.(*live.AgentControl)
     		if c.Label == "" {
    -			continue
    +			return true
     		}
     		labeled := &LabeledAgent{
     			Tag:   t.Tag,
    @@ -50,11 +47,12 @@ outter:
     			if l.Tag == labeled.Tag {
     				old[i].Label = labeled.Label // update label
     				old[i] = l
    -				continue outter
    +				return true // continue outter loop (simulated by returning true)
     			}
     		}
     		labeledAgents = append(labeledAgents, *labeled)
    -	}
    +		return true
    +	})
     	labeledAgents = append(labeledAgents, old...)
     	if len(labeledAgents) == 0 {
     		return
    @@ -85,8 +83,8 @@ func RefreshAgentLabel(a *def.Emp3r0rAgent) (label string) {
     	}
     	for _, labeled := range labeledAgents {
     		if a.Tag == labeled.Tag {
    -			if live.AgentControlMap[a] != nil {
    -				live.AgentControlMap[a].Label = labeled.Label
    +			if val, ok := live.AgentControlMap.Load(a); ok {
    +				val.(*live.AgentControl).Label = labeled.Label
     			}
     			return labeled.Label
     		}
    @@ -121,7 +119,9 @@ func SetAgentLabel(agentID string, label string) error {
     		return fmt.Errorf("agent does not exist: %s", agentID)
     	}
     
    -	live.AgentControlMap[target].Label = label // set label
    +	if val, ok := live.AgentControlMap.Load(target); ok {
    +		val.(*live.AgentControl).Label = label // set label
    +	}
     	PersistLabeledAgentsToFile()
     	logging.Successf("%s has been labeled as %s", target.Tag, label)
     	return nil
    
  • core/internal/cc/base/agents/mgr.go+63 68 modified
    @@ -16,43 +16,44 @@ import (
     )
     
     func GetConnectedAgents() []*def.Emp3r0rAgent {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	agents := make([]*def.Emp3r0rAgent, 0, len(live.AgentControlMap))
    -	for agent := range live.AgentControlMap {
    +	var agents []*def.Emp3r0rAgent
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		agent := key.(*def.Emp3r0rAgent)
     		shortID := fmt.Sprintf("%x", sha1.Sum([]byte(agent.UUID+agent.UUIDSig)))
     		if len(shortID) > 8 {
     			shortID = shortID[:8]
     		}
     		agent.ShortID = shortID
     		agents = append(agents, agent)
    -	}
    +		return true
    +	})
     	return agents
     }
     
     // GetAgentByIndex find target from def.AgentControlMap via control index, return nil if not found
     func GetAgentByIndex(index int) (target *def.Emp3r0rAgent) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for t, ctl := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		t := key.(*def.Emp3r0rAgent)
    +		ctl := value.(*live.AgentControl)
     		if ctl.Index == index {
     			target = t
    -			break
    +			return false // stop iteration
     		}
    -	}
    +		return true
    +	})
     	return
     }
     
     // GetAgentByTag find target from def.AgentControlMap via tag, return nil if not found
     func GetAgentByTag(tag string) (target *def.Emp3r0rAgent) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for t := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		t := key.(*def.Emp3r0rAgent)
     		if t.Tag == tag {
     			target = t
    -			break
    +			return false // stop iteration
     		}
    -	}
    +		return true
    +	})
     	if target == nil {
     		for _, t := range live.AgentList {
     			if t.Tag == tag {
    @@ -66,14 +67,14 @@ func GetAgentByTag(tag string) (target *def.Emp3r0rAgent) {
     
     // GetAgentByUUID find target from def.AgentControlMap via UUID, return nil if not found
     func GetAgentByUUID(uuid string) (target *def.Emp3r0rAgent) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for t := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		t := key.(*def.Emp3r0rAgent)
     		if t.UUID == uuid {
     			target = t
    -			break
    +			return false // stop iteration
     		}
    -	}
    +		return true
    +	})
     	if target == nil {
     		for _, t := range live.AgentList {
     			if t.UUID == uuid {
    @@ -87,24 +88,25 @@ func GetAgentByUUID(uuid string) (target *def.Emp3r0rAgent) {
     
     // IsAgentExistByUUID is agent already in target list?
     func IsAgentExistByUUID(uuid string) bool {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for a := range live.AgentControlMap {
    +	exists := false
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.UUID == uuid {
    -			return true
    +			exists = true
    +			return false // stop iteration
     		}
    -	}
    -
    -	return false
    +		return true
    +	})
    +	return exists
     }
     
     // GetTargetFromH2Conn find target from def.AgentControlMap via HTTP2 connection ID, return nil if not found
     func GetTargetFromH2Conn(conn *h2conn.Conn) (target *def.Emp3r0rAgent) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for t, ctrl := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		t := key.(*def.Emp3r0rAgent)
    +		ctrl := value.(*live.AgentControl)
     		if ctrl.Conn == nil {
    -			continue
    +			return true
     		}
     		// Check keys (not valid if using encryption, but kept for safety if wrappers change)
     		// We cannot directly compare net.Conn with *h2conn.Conn if they are not compatible.
    @@ -116,22 +118,22 @@ func GetTargetFromH2Conn(conn *h2conn.Conn) (target *def.Emp3r0rAgent) {
     			if wrapped, ok := secure.Conn.(*transport.ByteReadWriteCloser); ok {
     				if wrapped.ReadWriteCloser == conn {
     					target = t
    -					break
    +					return false // stop iteration
     				}
     			}
     		}
    -	}
    +		return true
    +	})
     	return
     }
     
     // SendMessageToAgent send MsgTunData to agent
     func SendMessageToAgent(msg_data *def.MsgTunData, agent *def.Emp3r0rAgent) (err error) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	ctrl := live.AgentControlMap[agent]
    -	if ctrl == nil {
    +	val, ok := live.AgentControlMap.Load(agent)
    +	if !ok {
     		return fmt.Errorf("Send2Agent (%s): Target is not connected", msg_data.CmdSlice)
     	}
    +	ctrl := val.(*live.AgentControl)
     	if ctrl.Conn == nil {
     		return fmt.Errorf("Send2Agent (%s): Target is not connected", msg_data.CmdSlice)
     	}
    @@ -167,52 +169,45 @@ func SetActiveAgent(identifier string) {
     
     // IsAgentExistByTag is agent already in target list?
     func IsAgentExistByTag(tag string) bool {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	for a := range live.AgentControlMap {
    +	exists := false
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.Tag == tag {
    -			return true
    +			exists = true
    +			return false // stop iteration
     		}
    -	}
    -
    -	return false
    +		return true
    +	})
    +	return exists
     }
     
     // IsAgentExist is agent already in target list?
     func IsAgentExist(t *def.Emp3r0rAgent) bool {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	return IsAgentExistLocked(t)
    -}
    -
    -// IsAgentExistLocked checks if agent exists (caller must hold lock)
    -func IsAgentExistLocked(t *def.Emp3r0rAgent) bool {
    -	for a := range live.AgentControlMap {
    +	exists := false
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.UUID == t.UUID {
    -			return true
    +			exists = true
    +			return false // stop iteration
     		}
    -	}
    -	return false
    +		return true
    +	})
    +	return exists
     }
     
     // AssignAgentIndex assign an index number to new agent
     func AssignAgentIndex() (index int) {
    -	live.AgentControlMapMutex.RLock()
    -	defer live.AgentControlMapMutex.RUnlock()
    -	return AssignAgentIndexLocked()
    -}
    -
    -// AssignAgentIndexLocked assigns index (caller must hold lock)
    -func AssignAgentIndexLocked() (index int) {
    -	// index is 0 for the first agent
    -	if len(live.AgentControlMap) == 0 {
    -		return 0
    -	}
    -
     	// loop thru agent list and get all index numbers
     	index_list := make([]int, 0)
    -	for _, c := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		c := value.(*live.AgentControl)
     		index_list = append(index_list, c.Index)
    +		return true
    +	})
    +
    +	// index is 0 for the first agent
    +	if len(index_list) == 0 {
    +		return 0
     	}
     
     	// sort
    
  • core/internal/cc/base/ftp/file_transfer.go+1 3 modified
    @@ -191,9 +191,7 @@ func GetFile(file_path string, agent *def.Emp3r0rAgent) (ftpSh *network.StreamHa
     	ftpSh.Token = fmt.Sprintf("%s-%s", util.RandMD5String(), fileinfo.Checksum)
     	ftpSh.Buf = make(chan []byte)
     	ftpSh.BufSize = 1024 * 8
    -	network.FTPMutex.Lock()
    -	network.FTPStreams[file_path] = ftpSh
    -	network.FTPMutex.Unlock()
    +	network.FTPStreams.Store(file_path, ftpSh)
     
     	// h2x
     	ftpSh.H2x = new(def.H2Conn)
    
  • core/internal/cc/base/ftp/file_transfer_interface.go+2 1 modified
    @@ -97,7 +97,8 @@ func DownloadFromAgent(target *def.Emp3r0rAgent, filePath string, isRecursive bo
     
     			// wait for file to be downloaded
     			for {
    -				if sh, ok := network.FTPStreams[file]; ok {
    +				if val, ok := network.FTPStreams.Load(file); ok {
    +					sh := val.(*network.StreamHandler)
     					if ftpSh.Token == sh.Token {
     						util.TakeABlink()
     						continue
    
  • core/internal/cc/base/ftp/handler_ftp.go+7 7 modified
    @@ -85,12 +85,14 @@ func HandleFTPTransfer(sh *network.StreamHandler, wrt http.ResponseWriter, req *
     
     	// Determine file paths.
     	filename := ""
    -	for fname, persh := range network.FTPStreams {
    +	network.FTPStreams.Range(func(fname, value interface{}) bool {
    +		persh := value.(*network.StreamHandler)
     		if sh.Token == persh.Token {
    -			filename = fname
    -			break
    +			filename = fname.(string)
    +			return false // stop iteration
     		}
    -	}
    +		return true
    +	})
     	if filename == "" {
     		logging.Errorf("Failed to parse filename for token %s", sh.Token)
     		return
    @@ -154,9 +156,7 @@ func HandleFTPTransfer(sh *network.StreamHandler, wrt http.ResponseWriter, req *
     			}
     		}
     		sh.H2x.Cancel()
    -		network.FTPMutex.Lock()
    -		delete(network.FTPStreams, mapKey)
    -		network.FTPMutex.Unlock()
    +		network.FTPStreams.Delete(mapKey)
     		logging.Warningf("Closed FTP connection from %s", req.RemoteAddr)
     		err = os.Remove(lock)
     		if err != nil {
    
  • core/internal/cc/base/network/handler_portfwd.go+9 8 modified
    @@ -66,11 +66,12 @@ func HandlePortMapping(sh *StreamHandler, wrt http.ResponseWriter, req *http.Req
     		logging.Errorf("Parse UUID failed from %s: %v", req.RemoteAddr, err)
     		return
     	}
    -	pf, exist := PortFwds[sessionID.String()]
    +	val, exist := PortFwds.Load(sessionID.String())
     	if !exist {
     		logging.Debugf("Port mapping session %s unknown. Did you remove it?", sessionID.String())
     		return
     	}
    +	pf := val.(*PortFwdSession)
     	pf.Sh = make(map[string]*StreamHandler)
     	if !isSubSession {
     		pf.Sh[sessionID.String()] = sh
    @@ -100,7 +101,8 @@ func HandlePortMapping(sh *StreamHandler, wrt http.ResponseWriter, req *http.Req
     			logging.Debugf("Closed sub-connection %s", origToken)
     			return
     		}
    -		if pf, exist = PortFwds[sessionID.String()]; exist {
    +		if val, exist := PortFwds.Load(sessionID.String()); exist {
    +			pf := val.(*PortFwdSession)
     			pf.Cancel()
     		} else {
     			logging.Debugf("Port mapping %s not found (likely deleted)", sessionID.String())
    @@ -109,7 +111,8 @@ func HandlePortMapping(sh *StreamHandler, wrt http.ResponseWriter, req *http.Req
     		logging.Debugf("Closed port forwarding connection from %s", req.RemoteAddr)
     	}()
     	for pf.Ctx.Err() == nil {
    -		if _, exist := PortFwds[sessionID.String()]; !exist {
    +		_, exist := PortFwds.Load(sessionID.String())
    +		if !exist {
     			logging.Warningf("Port mapping %s disconnected", sessionID.String())
     			return
     		}
    @@ -124,13 +127,11 @@ func DeletePortFwdSession(sessionID string) error {
     		return fmt.Errorf("no session ID provided")
     	}
     
    -	PortFwdsMutex.Lock()
    -	defer PortFwdsMutex.Unlock()
    -
    -	session, exists := PortFwds[sessionID]
    +	val, exists := PortFwds.Load(sessionID)
     	if !exists {
     		return fmt.Errorf("session %s not found", sessionID)
     	}
    +	session := val.(*PortFwdSession)
     
     	// Tell agent to delete the port mapping
     	err := session.SendCmdFunc(fmt.Sprintf("%s --id %s", def.C2CmdDeletePortFwd, sessionID), "", session.Agent.Tag)
    @@ -140,7 +141,7 @@ func DeletePortFwdSession(sessionID string) error {
     
     	// Cancel and delete locally
     	session.Cancel()
    -	delete(PortFwds, sessionID)
    +	PortFwds.Delete(sessionID)
     
     	if session.UnregisterFunc != nil {
     		if err = session.UnregisterFunc(sessionID); err != nil {
    
  • core/internal/cc/base/network/portfwd_session.go+5 10 modified
    @@ -55,9 +55,7 @@ func (pf *PortFwdSession) InitReversedPortFwd() (err error) {
     	}
     	pf.Reverse = true
     	pf.Agent = live.ActiveAgent
    -	PortFwdsMutex.Lock()
    -	PortFwds[fwdID] = pf
    -	PortFwdsMutex.Unlock()
    +	PortFwds.Store(fwdID, pf)
     
     	cmd := fmt.Sprintf("%s --to %s --shID %s --operation reverse", def.C2CmdPortFwd, listenPort, fwdID)
     	err = pf.SendCmdFunc(cmd, "", pf.Agent.Tag)
    @@ -224,9 +222,7 @@ func (pf *PortFwdSession) RunPortFwd() (err error) {
     	if pf.Description == "" {
     		pf.Description = fmt.Sprintf("Agent to CC mapping (%s)", pf.Protocol)
     	}
    -	PortFwdsMutex.Lock()
    -	PortFwds[fwdID] = pf
    -	PortFwdsMutex.Unlock()
    +	PortFwds.Store(fwdID, pf)
     
     	if pf.RegisterFunc != nil {
     		req := def.PortFwdRequest{
    @@ -251,9 +247,7 @@ func (pf *PortFwdSession) RunPortFwd() (err error) {
     		if udp_listener != nil {
     			udp_listener.Close()
     		}
    -		PortFwdsMutex.Lock()
    -		defer PortFwdsMutex.Unlock()
    -		delete(PortFwds, fwdID)
    +		PortFwds.Delete(fwdID)
     		if pf.UnregisterFunc != nil {
     			if err = pf.UnregisterFunc(fwdID); err != nil {
     				logging.Errorf("cleanup: failed to unregister %s: %v", fwdID, err)
    @@ -319,10 +313,11 @@ func (pf *PortFwdSession) RunPortFwd() (err error) {
     	}
     
     	for ctx.Err() == nil {
    -		p, exist := PortFwds[fwdID]
    +		val, exist := PortFwds.Load(fwdID)
     		if !exist {
     			return
     		}
    +		p := val.(*PortFwdSession)
     		if p.Sh == nil {
     			time.Sleep(100 * time.Millisecond)
     			continue
    
  • core/internal/cc/base/network/server.go+3 6 modified
    @@ -19,12 +19,9 @@ var (
     	// Shared stream handlers and maps
     	RShellStream  = &StreamHandler{H2x: nil, BufSize: def.RShellBufSize, Buf: make(chan []byte)}
     	ProxyStream   = &StreamHandler{H2x: nil, BufSize: def.ProxyBufSize, Buf: make(chan []byte)}
    -	FTPStreams    = make(map[string]*StreamHandler)
    -	FTPMutex      = &sync.Mutex{}
    -	RShellStreams = make(map[string]*StreamHandler)
    -	RShellMutex   = &sync.Mutex{}
    -	PortFwds      = make(map[string]*PortFwdSession)
    -	PortFwdsMutex = &sync.Mutex{}
    +	FTPStreams    sync.Map
    +	RShellStreams sync.Map
    +	PortFwds      sync.Map
     )
     
     // StreamHandler allows the HTTP handler to use H2Conn.
    
  • core/internal/cc/base/relay/server.go+11 3 modified
    @@ -49,11 +49,19 @@ func dispatcher(wrt http.ResponseWriter, req *http.Request) {
     	api = transport.WebRoot + "/" + api
     	switch api {
     	case transport.Upload2AgentAPI:
    -		for _, sh := range network.FTPStreams {
    +		var targetSH *network.StreamHandler
    +		network.FTPStreams.Range(func(_, value interface{}) bool {
    +			sh := value.(*network.StreamHandler)
     			if token == sh.Token {
    -				ftp.HandleFTPTransfer(sh, wrt, req)
    -				return
    +				targetSH = sh
    +				return false // stop iteration
     			}
    +			return true
    +		})
    +
    +		if targetSH != nil {
    +			ftp.HandleFTPTransfer(targetSH, wrt, req)
    +			return
     		}
     		logging.Debugf("FTP stream not found: %s", token)
     		wrt.WriteHeader(http.StatusNotFound)
    
  • core/internal/cc/controllers/command.go+1 3 modified
    @@ -30,9 +30,7 @@ func ExecuteCommand(cmd, jobID, agentTag string) error {
     	}
     
     	// Record command time immediately
    -	live.CmdTimeMutex.Lock()
    -	live.CmdTime[jobID] = time.Now().Format("2006-01-02 15:04:05.999999999 -0700 MST")
    -	live.CmdTimeMutex.Unlock()
    +	live.CmdTime.Store(jobID, time.Now().Format("2006-01-02 15:04:05.999999999 -0700 MST"))
     
     	// Send command asynchronously to avoid blocking
     	go func() {
    
  • core/internal/cc/controllers/portfwd.go+36 28 modified
    @@ -7,7 +7,6 @@ import (
     	"github.com/jm33-m0/emp3r0r/core/internal/cc/base/network"
     	c2context "github.com/jm33-m0/emp3r0r/core/internal/cc/context"
     	"github.com/jm33-m0/emp3r0r/core/internal/cc/modules"
    -	"github.com/jm33-m0/emp3r0r/core/internal/def"
     )
     
     // PortMapping represents a single port forward session
    @@ -26,30 +25,46 @@ type PortMapping struct {
     func GetActiveForwards() ([]PortMapping, error) {
     	mappings := []PortMapping{}
     
    -	for id, portmap := range network.PortFwds {
    +	network.PortFwds.Range(func(id, value interface{}) bool {
    +		portmap := value.(*network.PortFwdSession)
     		// Skip invalid sessions
     		if portmap.Sh == nil {
     			portmap.Cancel()
    -			continue
    +			return true // continue iteration
     		}
     
     		bindAddr := portmap.BindAddr
     		if bindAddr == "" {
     			bindAddr = "127.0.0.1"
     		}
     
    -		mapping := PortMapping{
    -			ID:          id,
    -			LocalPort:   portmap.Lport,
    -			RemoteAddr:  portmap.To,
    -			BindAddr:    bindAddr,
    -			AgentTag:    portmap.Agent.Tag,
    -			Description: portmap.Description,
    -			IsReverse:   portmap.Reverse,
    +		// Build local and remote addresses
    +		localPort := bindAddr + ":" + portmap.Lport
    +		remoteAddr := portmap.To
    +
    +		// Add context for reverse vs forward
    +		var description string
    +		if portmap.Reverse {
    +			localPort = portmap.Lport + " (Agent)"
    +			remoteAddr = portmap.To + " (CC)"
    +			description = fmt.Sprintf("Reverse: %s -> %s", localPort, remoteAddr)
    +		} else {
    +			localPort = localPort + " (CC)"
    +			remoteAddr = remoteAddr + " (Agent)"
    +			description = fmt.Sprintf("Forward: %s -> %s", localPort, remoteAddr)
     		}
     
    -		mappings = append(mappings, mapping)
    -	}
    +		mappings = append(mappings, PortMapping{ // Changed sessions to mappings, def.PortFwdSession to PortMapping
    +			ID:          id.(string),
    +			LocalPort:   localPort,
    +			RemoteAddr:  remoteAddr,
    +			BindAddr:    bindAddr,
    +			AgentTag:    portmap.Agent.Tag,
    +			Description: description,
    +			IsReverse:   portmap.Reverse, // Changed Reverse to IsReverse
    +		})
    +		return true
    +	})
     
     	return mappings, nil
     }
    @@ -130,25 +145,18 @@ func AddForward(ctx *c2context.C2Context) error {
     func RemoveForward(lport, to string, agentTag string) error {
     	found := false
     
    -	for id, session := range network.PortFwds {
    +	network.PortFwds.Range(func(id, value any) bool {
    +		session := value.(*network.PortFwdSession)
     		if session.To == to && session.Lport == lport && session.Agent.Tag == agentTag {
    -			session.Cancel() // cancel the PortFwd session
    -			delete(network.PortFwds, id)
    -
    -			// Tell the agent to close connection
    -			cmd := fmt.Sprintf("%s --shID %s --operation stop", def.C2CmdPortFwd, id)
    -			sendCMDerr := modules.CmdSender(cmd, "", agentTag)
    -			if sendCMDerr != nil {
    -				return fmt.Errorf("failed to send stop command to agent: %w", sendCMDerr)
    -			}
    -
    +			session.Cancel()
    +			network.PortFwds.Delete(id)
     			found = true
    -			break
    +			return false // stop iteration
     		}
    -	}
    -
    +		return true
    +	})
     	if !found {
    -		return fmt.Errorf("could not find port mapping (to %s, listening on %s)", to, lport)
    +		return fmt.Errorf("port mapping (to %s, listening on %s) not found for agent %s", to, lport, agentTag)
     	}
     
     	return nil
    
  • core/internal/cc/controllers/response_processor.go+2 5 modified
    @@ -85,11 +85,8 @@ func ProcessAgentResponse(data *def.MsgTunData) (*ProcessedResponse, error) {
     	live.CmdResults.Store(data.JobID, resp.Output)
     
     	// Calculate time spent
    -	live.CmdTimeMutex.Lock()
    -	cmdtime, ok := live.CmdTime[data.JobID]
    -	live.CmdTimeMutex.Unlock()
    -
    -	if ok {
    +	if val, ok := live.CmdTime.Load(data.JobID); ok {
    +		cmdtime := val.(string)
     		startTime, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", cmdtime)
     		if err == nil {
     			resp.TimeSpent = time.Since(startTime)
    
  • core/internal/cc/jobs/manager.go+11 15 modified
    @@ -15,9 +15,7 @@ import (
     
     var (
     	// Jobs holds all jobs, key is JobID
    -	Jobs = make(map[string]*def.Job)
    -	// JobsMutex protects Jobs map
    -	JobsMutex = &sync.RWMutex{}
    +	Jobs sync.Map
     )
     
     // CreateJob creates a new job and saves it to Jobs map
    @@ -31,17 +29,16 @@ func CreateJob(name, module, agentTag string) *def.Job {
     		Status:   def.JobStatusPending,
     	}
     
    -	JobsMutex.Lock()
    -	defer JobsMutex.Unlock()
    -	Jobs[job.ID] = job
    +	Jobs.Store(job.ID, job)
     	return job
     }
     
     // GetJob retrieves a job by ID
     func GetJob(id string) *def.Job {
    -	JobsMutex.RLock()
    -	defer JobsMutex.RUnlock()
    -	return Jobs[id]
    +	if val, ok := Jobs.Load(id); ok {
    +		return val.(*def.Job)
    +	}
    +	return nil
     }
     
     // HandleOutput appends output to job's log file or prints to console
    @@ -75,12 +72,11 @@ func HandleOutput(jobID string, output []byte) {
     
     // GetJobs returns a list of all jobs
     func GetJobs() []*def.Job {
    -	JobsMutex.RLock()
    -	defer JobsMutex.RUnlock()
    -	jobs := make([]*def.Job, 0, len(Jobs))
    -	for _, job := range Jobs {
    -		jobs = append(jobs, job)
    -	}
    +	var jobs []*def.Job
    +	Jobs.Range(func(key, value interface{}) bool {
    +		jobs = append(jobs, value.(*def.Job))
    +		return true
    +	})
     	return jobs
     }
     
    
  • core/internal/cc/modules/modportfwd.go+20 12 modified
    @@ -52,20 +52,22 @@ func ModulePortFwd(ctx *c2context.C2Context) {
     	switch switchOpt {
     	case "off":
     		// ugly, i know, it will delete port mappings matching current lport-to combination
    -		for id, session := range network.PortFwds {
    +		found := false
    +		network.PortFwds.Range(func(id, value interface{}) bool {
    +			session := value.(*network.PortFwdSession)
     			toOpt, ok := ctx.Flags["to"]
     			if !ok {
     				logging.Errorf("Option 'to' not found")
    -				return
    +				return false // stop iteration
     			}
     			listenPortOpt, ok := ctx.Flags["listen_port"]
     			if !ok {
     				logging.Errorf("Option 'listen_port' not found")
    -				return
    +				return false // stop iteration
     			}
     			if session.To == toOpt && session.Lport == listenPortOpt {
    -				session.Cancel()             // cancel the PortFwd session
    -				delete(network.PortFwds, id) // remove from port mapping list
    +				session.Cancel()            // cancel the PortFwd session
    +				network.PortFwds.Delete(id) // remove from port mapping list
     
     				// tell the agent to close connection
     				// make sure handler returns
    @@ -74,12 +76,17 @@ func ModulePortFwd(ctx *c2context.C2Context) {
     				sendCMDerr := CmdSender(cmd, "", activeAgent.Tag)
     				if sendCMDerr != nil {
     					logging.Errorf("SendCmd: %v", sendCMDerr)
    -					return
     				}
    -				return
    +				found = true
    +				return false // stop iteration
     			}
    -			logging.Errorf("Could not find port mapping (to %s, listening on %s)",
    -				toOpt, listenPortOpt)
    +			return true
    +		})
    +
    +		if !found {
    +			toOpt := ctx.Flags["to"]
    +			listenPortOpt := ctx.Flags["listen_port"]
    +			logging.Errorf("Could find port mapping (to %s, listening on %s)", toOpt, listenPortOpt)
     		}
     	case "reverse": // expose a dest from CC to agent
     		var pf network.PortFwdSession
    @@ -234,7 +241,8 @@ func moduleProxy(ctx *c2context.C2Context) {
     			}()
     		}
     	case "off":
    -		for id, session := range network.PortFwds {
    +		network.PortFwds.Range(func(id, value interface{}) bool {
    +			session := value.(*network.PortFwdSession)
     			if session.Description == pf.Description ||
     				session.Description == pfu.Description {
     				session.Cancel() // cancel the PortFwd session
    @@ -245,10 +253,10 @@ func moduleProxy(ctx *c2context.C2Context) {
     				err := CmdSender(cmd, "", session.Agent.Tag)
     				if err != nil {
     					logging.Errorf("SendCmd: %v", err)
    -					return
     				}
     			}
    -		}
    +			return true
    +		})
     	default:
     		logging.Errorf("Unknown operation '%s'", status)
     	}
    
  • core/internal/cc/modules/modshell.go+3 1 modified
    @@ -1,14 +1,16 @@
     package modules
     
     import (
    +	"sync"
    +
     	"github.com/jm33-m0/emp3r0r/core/internal/cc/base/agents"
     	c2context "github.com/jm33-m0/emp3r0r/core/internal/cc/context"
     	"github.com/jm33-m0/emp3r0r/core/internal/def"
     	"github.com/jm33-m0/emp3r0r/core/lib/logging"
     )
     
     // RShellStatus stores errors from reverseBash
    -var RShellStatus = make(map[string]error)
    +var RShellStatus sync.Map
     
     // ModuleCmd exec cmd on target
     func ModuleCmd(ctx *c2context.C2Context) {
    
  • core/internal/cc/modules/portfwd_data.go+6 4 modified
    @@ -18,11 +18,12 @@ func GetPortFwdSessions() []def.PortFwdSession {
     
     	var sessions []def.PortFwdSession
     
    -	for id, portmap := range network.PortFwds {
    +	network.PortFwds.Range(func(id, value interface{}) bool {
    +		portmap := value.(*network.PortFwdSession)
     		// Skip invalid sessions
     		if portmap.Sh == nil {
     			portmap.Cancel()
    -			continue
    +			return true // continue iteration
     		}
     
     		bindAddr := portmap.BindAddr
    @@ -44,15 +45,16 @@ func GetPortFwdSessions() []def.PortFwdSession {
     		}
     
     		sessions = append(sessions, def.PortFwdSession{
    -			ID:          id,
    +			ID:          id.(string),
     			LocalPort:   localPort,
     			RemoteAddr:  remoteAddr,
     			BindAddr:    bindAddr,
     			AgentTag:    portmap.Agent.Tag,
     			Description: portmap.Description,
     			Reverse:     portmap.Reverse,
     		})
    -	}
    +		return true
    +	})
     
     	return sessions
     }
    
  • core/internal/cc/modules/ssh.go+35 15 modified
    @@ -7,6 +7,7 @@ import (
     	"os/exec"
     	"strconv"
     	"strings"
    +	"sync"
     	"time"
     
     	"github.com/google/uuid"
    @@ -27,7 +28,7 @@ type SSH_SHELL_Mapping struct {
     
     // shell - port mapping
     // one port for one shell
    -var SSHShellPort = make(map[string]*SSH_SHELL_Mapping)
    +var SSHShellPort sync.Map
     
     // SSHClient ssh to sshd server, returns the SSH connection command string
     // shell: the executable to run, eg. bash, python
    @@ -49,12 +50,16 @@ func SSHClient(shell, args, port string) (string, error) {
     	// SSHDShellPort is reserved
     	is_new_port_needed := (port == live.RuntimeConfig.SSHDShellPort && shell != "sftp")
     	// check if port mapping is already open, if yes, use it
    -	for s, mapping := range SSHShellPort {
    +	SSHShellPort.Range(func(key, value interface{}) bool {
    +		s := key.(string)
    +		mapping := value.(*SSH_SHELL_Mapping)
     		if s == shell && mapping.Agent == target {
     			port = mapping.ToPort
     			is_new_port_needed = false
    +			return false // stop iteration
     		}
    -	}
    +		return true
    +	})
     
     	if !util.IsCommandExist("ssh") {
     		return "", fmt.Errorf("ssh must be installed")
    @@ -77,24 +82,34 @@ func SSHClient(shell, args, port string) (string, error) {
     
     	// is port mapping already done?
     	port_mapping_exists := false
    -	for _, p := range network.PortFwds {
    +	network.PortFwds.Range(func(id, value interface{}) bool {
    +		p := value.(*network.PortFwdSession)
     		if p.Agent == target && p.To == to {
     			port_mapping_exists = true
    -			for s, ssh_mapping := range SSHShellPort {
    +			SSHShellPort.Range(func(key, value interface{}) bool {
    +				s := key.(string)
    +				ssh_mapping := value.(*SSH_SHELL_Mapping)
     				// one port for one shell
     				// if trying to open a different shell on the same port, change to a new port
     				if s != shell && ssh_mapping.ToPort == port {
    -					new_port := strconv.Itoa(util.RandInt(2048, 65535))
    -					logging.Warningf("Port %s has %s shell on it, restarting with a different port %s", port, s, new_port)
    -					live.SetOption("port", new_port)
    -					return SSHClient(shell, args, new_port)
    +					lport = "" // mark for recursion
    +					return false
     				}
    -			}
    +				return true
    +			})
     			// if a shell is already open, use it
     			logging.Warningf("Using existing port mapping %s -> remote:%s for shell %s", p.Lport, port, shell)
     			lport = p.Lport // use the correct port
    -			break
    +			return false    // stop iteration
     		}
    +		return true
    +	})
    +
    +	if port_mapping_exists && lport == "" {
    +		new_port := strconv.Itoa(util.RandInt(2048, 65535))
    +		logging.Warningf("Port collision or conflict, restarting with a different port %s", new_port)
    +		live.SetOption("port", new_port)
    +		return SSHClient(shell, args, new_port)
     	}
     
     	if !port_mapping_exists {
    @@ -152,12 +167,12 @@ func SSHClient(shell, args, port string) (string, error) {
     		pf.RegisterFunc = RegisterPortFwdFunc
     		go func() {
     			// remember the port mapping and shell and agent
    -			SSHShellPort[shell] = &SSH_SHELL_Mapping{
    +			SSHShellPort.Store(shell, &SSH_SHELL_Mapping{
     				Shell:   shell,
     				Agent:   target,
     				PortFwd: pf,
     				ToPort:  port,
    -			}
    +			})
     			err = pf.RunPortFwd()
     			if err != nil {
     				logging.Errorf("Start port mapping for sshd (%s): %v", shell, err)
    @@ -177,11 +192,16 @@ wait:
     			break
     		}
     		time.Sleep(50 * time.Millisecond)
    -		for _, p := range network.PortFwds {
    +		network.PortFwds.Range(func(_, value interface{}) bool {
    +			p := value.(*network.PortFwdSession)
     			if p.Agent.Tag == target.Tag && p.To == to {
     				port_mapping_exists = true
    -				break wait
    +				return false // stop iteration
     			}
    +			return true
    +		})
    +		if port_mapping_exists {
    +			break wait
     		}
     	}
     	if !port_mapping_exists {
    
  • core/internal/cc/operator/completer.go+2 3 modified
    @@ -105,8 +105,7 @@ type RemoteDirListingCache struct {
     }
     
     var (
    -	RemoteDirListing      = make(map[string]*RemoteDirListingCache)
    -	RemoteDirListingMutex = new(sync.RWMutex)
    +	RemoteDirListing sync.Map
     )
     
     // autocomplete items in current remote directory
    @@ -130,7 +129,7 @@ func listRemoteDir(ctx carapace.Context) carapace.Action {
     		Listing: listing,
     	}
     	cache.Ctx, cache.Cancel = context.WithTimeout(context.Background(), 2*time.Minute)
    -	RemoteDirListing[cache.CWD] = cache
    +	RemoteDirListing.Store(cache.CWD, cache)
     
     	return carapace.ActionValues(listing...)
     }
    
  • core/internal/cc/operator/connection_test.go+2 5 modified
    @@ -104,16 +104,13 @@ func TestOperatorConnection(t *testing.T) {
     	// Since "checkin" might not be a valid API handler or might require POST
     	t.Logf("Response status: %s", resp.Status)
     
    -	// Test sending a command
     	// Mock active agent
     	agentTag := "test-agent"
     	agent := &def.Emp3r0rAgent{Tag: agentTag}
    -	live.AgentControlMapMutex.Lock()
    -	live.AgentControlMap[agent] = &live.AgentControl{
    +	live.AgentControlMap.Store(agent, &live.AgentControl{
     		Index: 0,
     		Label: "test-label",
    -	}
    -	live.AgentControlMapMutex.Unlock()
    +	})
     
     	// Mock SendCmd
     	originalSendCmd := agents.SendCmd
    
  • core/internal/cc/server/dispatcher.go+12 0 modified
    @@ -19,6 +19,12 @@ import (
     
     // apiDispatcher routes requests to the correct handler.
     func apiDispatcher(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("apiDispatcher panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	vars := mux.Vars(req)
     
     	if vars["api"] == "" || vars["token"] == "" {
    @@ -133,6 +139,12 @@ func apiDispatcher(wrt http.ResponseWriter, req *http.Request) {
     
     // operationDispatcher routes operator requests to the correct handler.
     func operationDispatcher(w http.ResponseWriter, r *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("operationDispatcher panicked: %v", r)
    +			http.Error(w, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	vars := mux.Vars(r)
     	api := vars["api"]
     	logging.Debugf("Operator request: API: %s", api)
    
  • core/internal/cc/server/handler_checkin.go+34 48 modified
    @@ -22,8 +22,7 @@ import (
     
     var (
     	// rotationRateLimiter tracks key rotation timestamps per AgentUUID to prevent log flooding
    -	rotationRateLimiter = make(map[string][]time.Time)
    -	limiterMutex        sync.Mutex
    +	rotationRateLimiter sync.Map
     )
     
     // handleAgentCheckIn processes agent check-in requests.
    @@ -35,15 +34,14 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     	if token != "" && agents.IsAgentExistByUUID(token) {
     		agent := agents.GetAgentByUUID(token)
     		if agent != nil {
    -			live.AgentControlMapMutex.RLock()
    -			ctrl := live.AgentControlMap[agent]
    -			if ctrl != nil && ctrl.Conn != nil {
    -				logging.Warningf("handleAgentCheckIn: %s already connected, refusing duplicated checkin", token)
    -				wrt.WriteHeader(http.StatusForbidden)
    -				live.AgentControlMapMutex.RUnlock()
    -				return
    +			if val, ok := live.AgentControlMap.Load(agent); ok {
    +				ctrl := val.(*live.AgentControl)
    +				if ctrl.Conn != nil {
    +					logging.Warningf("handleAgentCheckIn: %s already connected, refusing duplicated checkin", token)
    +					wrt.WriteHeader(http.StatusForbidden)
    +					return
    +				}
     			}
    -			live.AgentControlMapMutex.RUnlock()
     		}
     	}
     
    @@ -85,16 +83,16 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     	// If agent is new, verify with provided key and pin it
     	isNew := true
     
    -	live.AgentControlMapMutex.RLock()
     	existingKey := ""
    -	for a := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.UUID == target.UUID {
     			existingKey = a.PublicKey
     			isNew = false
    -			break
    +			return false // stop iteration
     		}
    -	}
    -	live.AgentControlMapMutex.RUnlock()
    +		return true
    +	})
     
     	// If not in memory, check if it exists in DB (Persistent Session)
     	// If not in memory, check if it exists in DB (Persistent Session)
    @@ -114,21 +112,16 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     		if existingKey != "" && target.PublicKey != existingKey {
     			// KEY ROTATION DETECTED
     
    -			// Check rate limit for rotation events specifically
    -			limiterMutex.Lock()
    -			rotationRateLimiter[target.UUID] = append(rotationRateLimiter[target.UUID], time.Now())
    -			limiterMutex.Unlock()
    -
     			// Find if there is an active controller (Scenario A: Active Session)
     			var activeCtrl *live.AgentControl
    -			live.AgentControlMapMutex.RLock()
    -			for a, ctrl := range live.AgentControlMap {
    +			live.AgentControlMap.Range(func(key, value interface{}) bool {
    +				a := key.(*def.Emp3r0rAgent)
     				if a.UUID == target.UUID {
    -					activeCtrl = ctrl
    -					break
    +					activeCtrl = value.(*live.AgentControl)
    +					return false // stop iteration
     				}
    -			}
    -			live.AgentControlMapMutex.RUnlock()
    +				return true
    +			})
     
     			// Scenario A: Clone Attack (Parallel Session)
     			if activeCtrl != nil && activeCtrl.Conn != nil {
    @@ -141,20 +134,14 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     
     			// Scenario B: Rotation Request
     			// Check pending
    -			live.PendingKeyRotationsMutex.RLock()
    -			_, pending := live.PendingKeyRotations[target.UUID]
    -			live.PendingKeyRotationsMutex.RUnlock()
    -
    -			if pending {
    +			if _, pending := live.PendingKeyRotations.Load(target.UUID); pending {
     				// Already pending, just block
     				wrt.WriteHeader(http.StatusForbidden)
     				return
     			}
     
     			// Create Request
    -			live.PendingKeyRotationsMutex.Lock()
    -			live.PendingKeyRotations[target.UUID] = target.PublicKey
    -			live.PendingKeyRotationsMutex.Unlock()
    +			live.PendingKeyRotations.Store(target.UUID, target.PublicKey)
     
     			msg := fmt.Sprintf("CRITICAL: Agent %s requests key rotation. Run 'forget_agent %s' to remove old record and allow re-registration.", target.UUID, strconv.Quote(target.UUID))
     			logging.Warningf("%s", msg)
    @@ -185,20 +172,19 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     	// ------------------------------------------------------------
     	// SECURITY: DoS Protection (Rate Limiting)
     	// ------------------------------------------------------------
    -	limiterMutex.Lock()
    -	defer limiterMutex.Unlock()
    -
     	now := time.Now()
     	// Prune old timestamps (> 1 minute)
     	validTimestamps := []time.Time{}
    -	if timestamps, exists := rotationRateLimiter[target.UUID]; exists {
    +	if val, exists := rotationRateLimiter.Load(target.UUID); exists {
    +		timestamps := val.([]time.Time)
     		for _, t := range timestamps {
     			if now.Sub(t) < time.Minute {
     				validTimestamps = append(validTimestamps, t)
     			}
     		}
     	}
    -	rotationRateLimiter[target.UUID] = validTimestamps
    +	validTimestamps = append(validTimestamps, now)
    +	rotationRateLimiter.Store(target.UUID, validTimestamps)
     
     	// Check limit (10 rotations per minute)
     	if len(validTimestamps) > 10 {
    @@ -225,14 +211,11 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     		}
     	}
     
    -	live.AgentControlMapMutex.Lock()
    -	defer live.AgentControlMapMutex.Unlock()
    -
    -	if !agents.IsAgentExistLocked(target) {
    +	if !agents.IsAgentExist(target) {
     		// New agent - register it
    -		inx := agents.AssignAgentIndexLocked()
    +		inx := agents.AssignAgentIndex()
     		target.LastSeen = time.Now()
    -		live.AgentControlMap[target] = &live.AgentControl{Index: inx, Conn: nil}
    +		live.AgentControlMap.Store(target, &live.AgentControl{Index: inx, Conn: nil})
     		shortname := strings.Split(target.Tag, "-agent")[0]
     		if util.IsExist(agents.AgentsJSON) {
     			if l := agents.RefreshAgentLabel(target); l != "" {
    @@ -243,7 +226,9 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     	} else {
     		// Existing agent - refresh info
     		var existingKey *def.Emp3r0rAgent
    -		for a, ctrl := range live.AgentControlMap {
    +		live.AgentControlMap.Range(func(key, value interface{}) bool {
    +			a := key.(*def.Emp3r0rAgent)
    +			ctrl := value.(*live.AgentControl)
     			if a.UUID == target.UUID {
     				// if agent is already connected, it must be the same instance
     				// because we already checked for duplications
    @@ -278,9 +263,10 @@ func handleAgentCheckIn(wrt http.ResponseWriter, req *http.Request) {
     				a.Product = target.Product
     				a.LastSeen = time.Now()
     				existingKey = a
    -				break
    +				return false // stop iteration
     			}
    -		}
    +			return true
    +		})
     		shortname := strings.Split(target.Tag, "-agent")[0]
     		if util.IsExist(agents.AgentsJSON) {
     			if existingKey != nil {
    
  • core/internal/cc/server/handler_messagetun.go+19 15 modified
    @@ -39,15 +39,16 @@ func handleMessageTunnel(wrt http.ResponseWriter, req *http.Request) {
     		logging.Debugf("handleMessageTunnel exiting")
     		cancel()  // Signal goroutine to stop
     		wg.Wait() // Wait for goroutine to finish before returning
    -		live.AgentControlMapMutex.Lock()
    -		for t, c := range live.AgentControlMap {
    +		live.AgentControlMap.Range(func(key, value interface{}) bool {
    +			t := key.(*def.Emp3r0rAgent)
    +			c := value.(*live.AgentControl)
     			if c.Conn == secureConn {
    -				delete(live.AgentControlMap, t)
    +				live.AgentControlMap.Delete(t)
     				operatorBroadcastPrintf(logging.ERROR, "Agent dies... %s is disconnected", strconv.Quote(t.Name))
    -				break
    +				return false // stop iteration
     			}
    -		}
    -		live.AgentControlMapMutex.Unlock()
    +			return true
    +		})
     		_ = conn.Close()
     		logging.Debugf("handleMessageTunnel exited")
     	}()
    @@ -116,16 +117,19 @@ func handleMessageTunnel(wrt http.ResponseWriter, req *http.Request) {
     				return
     			}
     			shortname := agent.Name
    -			live.AgentControlMapMutex.Lock()
    -			if live.AgentControlMap[agent].Conn == nil {
    -				operatorBroadcastPrintf(logging.SUCCESS,
    -					"Knock.. Knock... Agent %s is connected",
    -					strconv.Quote(shortname))
    +			if val, ok := live.AgentControlMap.Load(agent); ok {
    +				ctrl := val.(*live.AgentControl)
    +				if ctrl.Conn == nil {
    +					operatorBroadcastPrintf(logging.SUCCESS,
    +						"Knock.. Knock... Agent %s is connected",
    +						strconv.Quote(shortname))
    +				}
    +				// Update control info and publish via Store to ensure memory visibility
    +				ctrl.Conn = secureConn
    +				ctrl.Ctx = ctx
    +				ctrl.Cancel = cancel
    +				live.AgentControlMap.Store(agent, ctrl)
     			}
    -			live.AgentControlMap[agent].Conn = secureConn
    -			live.AgentControlMap[agent].Ctx = ctx
    -			live.AgentControlMap[agent].Cancel = cancel
    -			live.AgentControlMapMutex.Unlock()
     
     			agent.LastSeen = time.Now()
     			if msg.Time != "" {
    
  • core/internal/cc/server/handler_messagetun_helper.go+8 10 modified
    @@ -72,20 +72,18 @@ func operatorBroadcastPrintf(msg_type, format string, a ...any) (err error) {
     
     // fwdMsg2Operators forwards a message to all connected operator sessions.
     func fwdMsg2Operators(msg def.MsgTunData) (err error) {
    -	for operator_session_id, operator := range OPERATORS {
    -		if operator == nil {
    -			continue
    +	OPERATORS.Range(func(id, value interface{}) bool {
    +		op, ok := value.(*operator_t)
    +		if !ok || op == nil || op.conn == nil {
    +			return true // continue iteration
     		}
    -		if operator.conn == nil {
    -			continue
    -		}
    -		encoder := cbor.NewEncoder(operator.conn)
    +		encoder := cbor.NewEncoder(op.conn)
     		err = encoder.Encode(msg)
     		if err != nil {
     			logging.Errorf("Failed to forward message to operator: %v", err)
    -			return
    +			return false // stop iteration on error
     		}
    -		logging.Debugf("Forwarded message %v to operator %s", msg, operator_session_id)
    -	}
    +		return true // continue iteration
    +	})
     	return
     }
    
  • core/internal/cc/server/operator.go+90 38 modified
    @@ -6,6 +6,7 @@ import (
     	"net/http"
     	"os"
     	"strings"
    +	"sync"
     	"time"
     
     	"github.com/fxamacker/cbor/v2"
    @@ -27,7 +28,7 @@ type operator_t struct {
     
     var (
     	// OPERATORS holds all operator connections
    -	OPERATORS = make(map[string]*operator_t)
    +	OPERATORS sync.Map
     
     	// SERVER_WG_CONFIG is the wireguard config for the server
     	SERVER_WG_CONFIG *netutil.WireGuardConfig
    @@ -44,6 +45,12 @@ func DecodeCBORBody[T any](wrt http.ResponseWriter, req *http.Request) (*T, erro
     }
     
     func handleSetActiveAgent(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleSetActiveAgent panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Decode CBOR request body
     	operation, err := DecodeCBORBody[def.Operation](wrt, req)
     	if err != nil {
    @@ -61,6 +68,12 @@ func handleSetActiveAgent(wrt http.ResponseWriter, req *http.Request) {
     }
     
     func handleSendCommand(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleSendCommand panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Decode CBOR request body
     	operation, err := DecodeCBORBody[def.Operation](wrt, req)
     	if err != nil {
    @@ -90,6 +103,12 @@ func handleSendCommand(wrt http.ResponseWriter, req *http.Request) {
     }
     
     func handleListAgents(wrt http.ResponseWriter, _ *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleListAgents panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Get all agents
     	agentsList := agents.GetConnectedAgents()
     
    @@ -100,6 +119,12 @@ func handleListAgents(wrt http.ResponseWriter, _ *http.Request) {
     }
     
     func handleForgetAgent(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleForgetAgent panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Decode CBOR request body to get Agent UUID
     	operation, err := DecodeCBORBody[def.Operation](wrt, req)
     	if err != nil {
    @@ -116,16 +141,15 @@ func handleForgetAgent(wrt http.ResponseWriter, req *http.Request) {
     	var agentDetails string = fmt.Sprintf("Agent %s", uuid)
     
     	// Try to get agent details from memory first (if connected/recently connected)
    -	live.AgentControlMapMutex.RLock()
     	var targetAgent *def.Emp3r0rAgent
    -	for a := range live.AgentControlMap {
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		a := key.(*def.Emp3r0rAgent)
     		if a.UUID == uuid {
     			targetAgent = a
    -			break
    +			return false // stop iteration
     		}
    -	}
    -	live.AgentControlMapMutex.RUnlock()
    -
    +		return true
    +	})
     	if targetAgent != nil {
     		agentDetails += fmt.Sprintf("\n  Tag: %s\n  Hostname: %s\n  IPs: %s\n  OS: %s",
     			targetAgent.Tag, targetAgent.Hostname, strings.Join(targetAgent.IPs, ", "), targetAgent.OS)
    @@ -152,35 +176,35 @@ func handleForgetAgent(wrt http.ResponseWriter, req *http.Request) {
     	}
     
     	// Remove from memory
    -	live.AgentControlMapMutex.Lock()
     	if targetAgent != nil {
    -		delete(live.AgentControlMap, targetAgent)
    +		live.AgentControlMap.Delete(targetAgent)
     		logging.Successf("Operator removed agent %s from memory", uuid)
     	}
    -	live.AgentControlMapMutex.Unlock()
    -
     	// Clean up any pending key rotations for this agent
    -	live.PendingKeyRotationsMutex.Lock()
    -	delete(live.PendingKeyRotations, uuid)
    -	live.PendingKeyRotationsMutex.Unlock()
    +	live.PendingKeyRotations.Delete(uuid)
     
     	wrt.WriteHeader(http.StatusOK)
     	wrt.Write([]byte(fmt.Sprintf("%s\n\nHas been forgotten.", agentDetails)))
     }
     
     func handleListPortFwds(wrt http.ResponseWriter, _ *http.Request) {
    -	network.PortFwdsMutex.Lock()
    -	defer network.PortFwdsMutex.Unlock()
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleListPortFwds panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     
     	var sessions []def.PortFwdSession
    -	for id, portmap := range network.PortFwds {
    +	network.PortFwds.Range(func(id, value any) bool {
    +		portmap := value.(*network.PortFwdSession)
     		bindAddr := portmap.BindAddr
     		if bindAddr == "" {
     			bindAddr = "127.0.0.1"
     		}
     
     		sessions = append(sessions, def.PortFwdSession{
    -			ID:          id,
    +			ID:          id.(string),
     			LocalPort:   portmap.Lport,
     			RemoteAddr:  portmap.To,
     			BindAddr:    bindAddr,
    @@ -189,7 +213,8 @@ func handleListPortFwds(wrt http.ResponseWriter, _ *http.Request) {
     			Reverse:     portmap.Reverse,
     			Protocol:    portmap.Protocol,
     		})
    -	}
    +		return true
    +	})
     
     	data, err := cbor.Marshal(sessions)
     	if err != nil {
    @@ -204,15 +229,20 @@ func handleListPortFwds(wrt http.ResponseWriter, _ *http.Request) {
     }
     
     func handleRegisterPortFwd(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleRegisterPortFwd panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Decode CBOR request body
     	pfReq, err := DecodeCBORBody[def.PortFwdRequest](wrt, req)
     	if err != nil {
     		return
     	}
     
     	// Register session in server's map
    -	network.PortFwdsMutex.Lock()
    -	network.PortFwds[pfReq.SessionID] = &network.PortFwdSession{
    +	network.PortFwds.Store(pfReq.SessionID, &network.PortFwdSession{
     		Lport:       pfReq.Lport,
     		To:          pfReq.To,
     		Description: pfReq.Description,
    @@ -221,30 +251,39 @@ func handleRegisterPortFwd(wrt http.ResponseWriter, req *http.Request) {
     		Agent: &def.Emp3r0rAgent{
     			Tag: pfReq.AgentTag,
     		},
    -	}
    -	network.PortFwdsMutex.Unlock()
    +	})
     
     	logging.Infof("Registered port mapping %s (%s) from operator", pfReq.SessionID, pfReq.Description)
     	wrt.WriteHeader(http.StatusOK)
     }
     
     func handleUnregisterPortFwd(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleUnregisterPortFwd panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	// Decode CBOR request body
     	sessionID, err := DecodeCBORBody[string](wrt, req)
     	if err != nil {
     		return
     	}
     
     	// Unregister session in server's map
    -	network.PortFwdsMutex.Lock()
    -	delete(network.PortFwds, *sessionID)
    -	network.PortFwdsMutex.Unlock()
    +	network.PortFwds.Delete(*sessionID)
     
     	logging.Infof("Unregistered port mapping %s from operator", *sessionID)
     	wrt.WriteHeader(http.StatusOK)
     }
     
     func handleGetCA(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleGetCA panicked: %v", r)
    +			http.Error(wrt, "Internal server error", http.StatusInternalServerError)
    +		}
    +	}()
     	caData, err := os.ReadFile(transport.CaCrtFile)
     	if err != nil {
     		logging.Errorf("Failed to read CA cert: %v", err)
    @@ -278,6 +317,11 @@ func handleGetCA(wrt http.ResponseWriter, req *http.Request) {
     
     // handleOperatorConn handles operator connections, this connection will be used to relay the message tunnel
     func handleOperatorConn(wrt http.ResponseWriter, req *http.Request) {
    +	defer func() {
    +		if r := recover(); r != nil {
    +			logging.Errorf("handleOperatorConn panicked: %v", r)
    +		}
    +	}()
     	conn, err := h2conn.Accept(wrt, req)
     	if err != nil {
     		http.Error(wrt, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
    @@ -286,7 +330,11 @@ func handleOperatorConn(wrt http.ResponseWriter, req *http.Request) {
     	operator_session := req.Header.Get("operator_session")
     
     	// Check if other operators are already connected
    -	activeSessionCount := len(OPERATORS)
    +	activeSessionCount := 0
    +	OPERATORS.Range(func(key, value interface{}) bool {
    +		activeSessionCount++
    +		return true
    +	})
     	if activeSessionCount > 0 {
     		logging.Warningf("⚠️  New operator %s connecting while %d session(s) active!", operator_session, activeSessionCount)
     
    @@ -309,23 +357,27 @@ func handleOperatorConn(wrt http.ResponseWriter, req *http.Request) {
     		return
     	}
     	logging.Infof("Operator %s connected to message tunnel from %s", operator_session, req.RemoteAddr)
    -	operator, ok := OPERATORS[operator_session]
    -	if !ok {
    -		OPERATORS[operator_session] = &operator_t{
    -			sessionID: operator_session,
    -			conn:      conn,
    -		}
    -	} else {
    -		operator.conn = conn
    -	}
    +	op, _ := OPERATORS.LoadOrStore(operator_session, &operator_t{
    +		sessionID: operator_session,
    +		conn:      conn,
    +	})
    +	operator := op.(*operator_t)
    +	operator.conn = conn
    +	OPERATORS.Store(operator_session, operator)
     
     	ctx, cancel := context.WithCancel(req.Context())
     	defer func() {
     		logging.Debugf("handleOperatorConn exiting")
    -		delete(OPERATORS, operator_session)
    +		OPERATORS.Delete(operator_session)
     
     		// If this was the last operator, disconnect all agents
    -		if len(OPERATORS) == 0 {
    +		lastOperator := true
    +		OPERATORS.Range(func(key, value interface{}) bool {
    +			lastOperator = false
    +			return false // stop iteration
    +		})
    +
    +		if lastOperator {
     			logging.Infof("Last operator disconnected, closing all agent connections")
     			agents.DisconnectAllAgents()
     		}
    
  • core/internal/cc/server/tls_server.go+9 4 modified
    @@ -41,9 +41,14 @@ func StartC2AgentTLSServer() {
     					return
     				}
     				// Process
    -				// Check if there are any active operators
    -				allowConn := len(OPERATORS) > 0
    -				respData, err := preflight.ProcessRequest(body, allowConn)
    +				// Preflight: only allow connections from operators
    +				hasOperators := false
    +				OPERATORS.Range(func(key, value any) bool {
    +					hasOperators = true
    +					return false // stop iteration
    +				})
    +
    +				respData, err := preflight.ProcessRequest(body, hasOperators)
     
     				if err != nil {
     					logging.Warningf("Preflight failed: %v", err)
    @@ -52,7 +57,7 @@ func StartC2AgentTLSServer() {
     				}
     
     				// Log decision only on success
    -				if allowConn {
    +				if hasOperators {
     					logging.Infof("Preflight: Allowed connection (Operators active)")
     				} else {
     					logging.Warningf("Preflight: Rejected connection (No operators)")
    
  • core/internal/live/agent.go+3 6 modified
    @@ -13,8 +13,7 @@ var (
     	CmdResults = sync.Map{}
     
     	// CmdTime store command time
    -	CmdTime      = make(map[string]string)
    -	CmdTimeMutex = &sync.Mutex{}
    +	CmdTime sync.Map
     )
     
     // AgentControl controller interface of a target
    @@ -28,13 +27,11 @@ type AgentControl struct {
     
     var (
     	// AgentControlMap target list, with control (tun) interface
    -	AgentControlMap      = make(map[*def.Emp3r0rAgent]*AgentControl)
    -	AgentControlMapMutex = sync.RWMutex{}
    +	AgentControlMap sync.Map
     
     	// AgentList list of connected agents
     	AgentList = make([]*def.Emp3r0rAgent, 0)
     	// PendingKeyRotations stores new public keys for agents that requested rotation
     	// key: UUID, value: PublicKey
    -	PendingKeyRotations      = make(map[string]string)
    -	PendingKeyRotationsMutex = sync.RWMutex{}
    +	PendingKeyRotations sync.Map
     )
    
  • core/internal/transport/sshproxy.go+5 21 modified
    @@ -60,12 +60,10 @@ func SSHRemoteFwdServer(port, password string, hostkey []byte) (err error) {
     
     // SSHReverseProxyClient dial SSHProxyServer, start a reverse proxy
     // serverAddr format: 127.0.0.1:22
    -// FIXME: when using KCP, port number calculation is wrong
     func SSHReverseProxyClient(ssh_serverAddr string, // SSH server address:port
     	password string, // SSH authentication password
     	proxyPort int, // local port to forward to remote, in here it should be Emp3r0rProxyPort
    -	reverseConns *map[string]context.CancelFunc,
    -	reverseConnsMutex *sync.Mutex,
    +	reverseConns *sync.Map,
     	socks5proxy *socks5.Server,
     	ctx context.Context, cancel context.CancelFunc,
     ) (err error) {
    @@ -89,7 +87,7 @@ func SSHReverseProxyClient(ssh_serverAddr string, // SSH server address:port
     	}()
     
     	return SSHRemoteFwdClient(ssh_serverAddr, password, nil,
    -		proxyPort, reverseConns, reverseConnsMutex, ctx, cancel)
    +		proxyPort, reverseConns, ctx, cancel)
     }
     
     // SSHRemoteFwdClient dial SSHRemoteFwdServer, forward local TCP port to remote server
    @@ -98,8 +96,7 @@ func SSHReverseProxyClient(ssh_serverAddr string, // SSH server address:port
     func SSHRemoteFwdClient(ssh_serverAddr, password string,
     	hostkey ssh.PublicKey, // ssh server public key
     	local_port int, // local port to forward to remote
    -	conns *map[string]context.CancelFunc, // record this connection
    -	connsMutex *sync.Mutex,
    +	conns *sync.Map, // record this connection
     	ctx context.Context, cancel context.CancelFunc,
     ) (err error) {
     	hostkey_callback := ssh.InsecureIgnoreHostKey()
    @@ -143,23 +140,10 @@ func SSHRemoteFwdClient(ssh_serverAddr, password string,
     		l.Close()
     	}()
     
    -	connsList := *conns
    -	if connsMutex != nil {
    -		connsMutex.Lock()
    -	}
    -	connsList[ssh_serverAddr] = cancel // record this connection
    -	if connsMutex != nil {
    -		connsMutex.Unlock()
    -	}
    +	conns.Store(ssh_serverAddr, cancel) // record this connection
     	toAddr := fmt.Sprintf("127.0.0.1:%d", local_port)
     	defer func() {
    -		if connsMutex != nil {
    -			connsMutex.Lock()
    -		}
    -		delete(connsList, ssh_serverAddr)
    -		if connsMutex != nil {
    -			connsMutex.Unlock()
    -		}
    +		conns.Delete(ssh_serverAddr)
     	}()
     
     	// forward to target local port
    
  • core/modules/shellcode_stager/test/e2e_test.go+28 28 modified
    @@ -20,6 +20,7 @@ import (
     	"path/filepath"
     	"strconv"
     	"strings"
    +	"sync"
     	"syscall"
     	"testing"
     	"time"
    @@ -174,16 +175,17 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     	}
     
     	// Reset live agent maps
    -	live.AgentControlMapMutex.Lock()
    -	live.AgentControlMap = make(map[*def.Emp3r0rAgent]*live.AgentControl)
    +	live.AgentControlMap = sync.Map{}
     	live.AgentList = make([]*def.Emp3r0rAgent, 0)
    -	live.AgentControlMapMutex.Unlock()
     
     	// Debug: verify maps are empty
    -	live.AgentControlMapMutex.RLock()
    -	logging.Debugf("AgentControlMap size after reset: %d", len(live.AgentControlMap))
    +	size := 0
    +	live.AgentControlMap.Range(func(key, value interface{}) bool {
    +		size++
    +		return true
    +	})
    +	logging.Debugf("AgentControlMap size after reset: %d", size)
     	logging.Debugf("AgentList size after reset: %d", len(live.AgentList))
    -	live.AgentControlMapMutex.RUnlock()
     
     	// Small delay to ensure map reset propagates
     	time.Sleep(100 * time.Millisecond)
    @@ -250,7 +252,7 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     	logging.Successf("Mock agent patched with config")
     
     	// Dummy operator for preflight
    -	server.OPERATORS["dummy"] = nil
    +	server.OPERATORS.Store("dummy", nil)
     
     	// 4. Start Real C2 Server
     	// Shutdown any existing server first
    @@ -417,14 +419,15 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     		}
     
     		// Check if agent has checked in (added to AgentControlMap) AND has an active connection
    -		live.AgentControlMapMutex.RLock()
    -		for k, v := range live.AgentControlMap {
    +		live.AgentControlMap.Range(func(key, value interface{}) bool {
    +			k := key.(*def.Emp3r0rAgent)
    +			v := value.(*live.AgentControl)
     			if k.Tag != "" && v.Conn != nil { // Wait for MsgTun connection
     				agent = k
    -				break
    +				return false // stop iteration
     			}
    -		}
    -		live.AgentControlMapMutex.RUnlock()
    +			return true
    +		})
     
     		if agent != nil {
     			logging.Successf("Agent checked in and connected! Tag: %s", agent.Tag)
    @@ -494,14 +497,14 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     	outputReceived := false
     	for i := 0; i < 20; i++ {
     		// Check connection status
    -		live.AgentControlMapMutex.RLock()
    -		if a, ok := live.AgentControlMap[agent]; ok && a.Conn != nil {
    -			// still connected
    -		} else {
    -			live.AgentControlMapMutex.RUnlock()
    -			t.Fatalf("Agent disconnected while waiting for command output!")
    +		if val, ok := live.AgentControlMap.Load(agent); ok {
    +			a := val.(*live.AgentControl)
    +			if a.Conn != nil {
    +				// still connected
    +			} else {
    +				t.Fatalf("Agent disconnected while waiting for command output!")
    +			}
     		}
    -		live.AgentControlMapMutex.RUnlock()
     
     		// Check result
     		if res, ok := live.CmdResults.Load(cmdID); ok {
    @@ -529,12 +532,10 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     	logging.Infof("Testing Agent Restart & Key Persistence...")
     
     	// Get first session key
    -	live.AgentControlMapMutex.RLock()
     	firstKey := ""
     	if agent != nil {
     		firstKey = agent.PublicKey
     	}
    -	live.AgentControlMapMutex.RUnlock()
     
     	if firstKey == "" {
     		t.Fatalf("Failed to get first session key")
    @@ -614,13 +615,12 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     	reconnected := false
     
     	for time.Since(startRestart) < 30*time.Second {
    -		live.AgentControlMapMutex.RLock()
    -		for k, v := range live.AgentControlMap {
    +		live.AgentControlMap.Range(func(key, value interface{}) bool {
    +			k := key.(*def.Emp3r0rAgent)
    +			v := value.(*live.AgentControl)
     			// Look for the same UUID
     			if k.UUID == agent.UUID && v.Conn != nil {
     				// Check PID to ensure it's a new process
    -				// k.Process might be nil if not fully populated yet, or old?
    -				// But handler_checkin updates the struct k points to.
     
     				if k.Process != nil && k.Process.PID != childPid {
     					// New Process detected!
    @@ -629,16 +629,16 @@ func TestAgentEndToEndLifecycle(t *testing.T) {
     					if k.PublicKey != firstKey {
     						logging.Errorf("Agent Logs (Stderr):\n%s", stderr.String())
     						logging.Errorf("Stager Logs (Stdout):\n%s", stdout.String())
    -						live.AgentControlMapMutex.RUnlock()
     						t.Fatalf("CRITICAL FAILURE: Agent Restarted with DIFFERENT Key!\nFirst: %s\nNew: %s", firstKey, k.PublicKey)
     					}
     
     					logging.Infof("New Agent PID: %d (Old: %d)", k.Process.PID, childPid)
     					reconnected = true
    +					return false // stop iteration
     				}
     			}
    -		}
    -		live.AgentControlMapMutex.RUnlock()
    +			return true
    +		})
     
     		if reconnected {
     			logging.Successf("Agent reconnected with SAME key. Persistence verified.")
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.