Location: apps/counterstrikesharp/src/FiveStack.Services/TimeoutSystem.cs:139 (game-server)
What: CanPause (lines 139-141) and IsAdminOrOrganizer (lines 477-479) grant the privileged pause/resume fast-path only when player.Clan equals "[administrator]", "[match_organizer]" or "[tournament_organizer]". But administrators/organizers connect through the PendingPlayers path, where PlayerConnected.cs:60 sets player.Clan = "[" + role + "]" from the role strings assigned in InitConnect.cs ("admin", "organizer", "streamer"). The resulting tags "[admin]"/"[organizer]"/"[streamer]" never equal the strings TimeoutSystem tests, and these off-lineup users are not in GetMemberFromLineup, so the role fallback returns false too.
Impact: An administrator or tournament organizer joins a live match to pause it and types the pause command. CanPause returns false (tag is "[admin]"/"[organizer]", not "[administrator]"), so instead of an immediate admin pause the code starts a team/captain vote or denies the action; RequestResume likewise cannot force a resume. Admin control over pause/resume is effectively broken.
Suggested fix: Make the clan-tag comparisons match the tags actually written ("[admin]"/"[organizer]"/"[streamer]"), or better, drive the privilege check off the PendingPlayers role / player role enum rather than the display clan string.
Verifier evidence
InitConnect.cs:83 PendingPlayers[steamId] = "streamer";; :144 PendingPlayers[steamId] = "admin";; :148 "streamer"; :152 PendingPlayers[steamId] = "organizer"; (none are "administrator"/"match_organizer"/"tournament_organizer"). PlayerConnected.cs:60 player.Clan = $"[{role}]"; (=> "[admin]"/"[organizer]"/"[streamer]"). PlayerConnected.cs:54 if (shouldKick && lineup_id == null) gates the PendingPlayers branch, so these users are off-lineup. TimeoutSystem.cs:139-141 player.Clan == "[administrator]" || player.Clan == "[match_organizer]" || player.Clan == "[tournament_organizer]" and identical at 477-479, never match. TimeoutSystem.cs:169-178 fallback via GetMemberFromLineup returns null (lineupPlayer==null => return false) for off-lineup users; same at 485-491.
Found by the 2026-07 multi-agent code audit; adversarially verified (CONFIRMED, P2). One of a batch of findings from that pass.
Location:
apps/counterstrikesharp/src/FiveStack.Services/TimeoutSystem.cs:139(game-server)What: CanPause (lines 139-141) and IsAdminOrOrganizer (lines 477-479) grant the privileged pause/resume fast-path only when player.Clan equals "[administrator]", "[match_organizer]" or "[tournament_organizer]". But administrators/organizers connect through the PendingPlayers path, where PlayerConnected.cs:60 sets player.Clan = "[" + role + "]" from the role strings assigned in InitConnect.cs ("admin", "organizer", "streamer"). The resulting tags "[admin]"/"[organizer]"/"[streamer]" never equal the strings TimeoutSystem tests, and these off-lineup users are not in GetMemberFromLineup, so the role fallback returns false too.
Impact: An administrator or tournament organizer joins a live match to pause it and types the pause command. CanPause returns false (tag is "[admin]"/"[organizer]", not "[administrator]"), so instead of an immediate admin pause the code starts a team/captain vote or denies the action; RequestResume likewise cannot force a resume. Admin control over pause/resume is effectively broken.
Suggested fix: Make the clan-tag comparisons match the tags actually written ("[admin]"/"[organizer]"/"[streamer]"), or better, drive the privilege check off the PendingPlayers role / player role enum rather than the display clan string.
Verifier evidence
InitConnect.cs:83
PendingPlayers[steamId] = "streamer";; :144PendingPlayers[steamId] = "admin";; :148"streamer"; :152PendingPlayers[steamId] = "organizer";(none are "administrator"/"match_organizer"/"tournament_organizer"). PlayerConnected.cs:60player.Clan = $"[{role}]";(=> "[admin]"/"[organizer]"/"[streamer]"). PlayerConnected.cs:54if (shouldKick && lineup_id == null)gates the PendingPlayers branch, so these users are off-lineup. TimeoutSystem.cs:139-141player.Clan == "[administrator]" || player.Clan == "[match_organizer]" || player.Clan == "[tournament_organizer]"and identical at 477-479, never match. TimeoutSystem.cs:169-178 fallback via GetMemberFromLineup returns null (lineupPlayer==null => return false) for off-lineup users; same at 485-491.Found by the 2026-07 multi-agent code audit; adversarially verified (CONFIRMED, P2). One of a batch of findings from that pass.