Skip to content

[Game Server] Timeout pause/resume clan-tag check never matches the assigned tags #552

Description

@Flegma

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2-mediumCode quality & robustnessaudit-2026-07Findings from the 2026-07 code audit / review passlogic-errorLogic or state machine bugservice:game-server5stackgg/game-server service

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions