mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-25 13:10:13 +00:00
80d50a6d92
Security finding (CWE-863): the SignalR user id was the bare UPN and every revoke cut that UPN across the hub. A tenant admin could add any UPN (a Global Admin, another customer's operator) and remove, disable or demote it in a loop, restarting that person's live connections in every tenant. - Negotiate binds the user id to the sign-in tenant plus principal key from the validated request context (SignalRGroupHelper.UserId); a caller without a principal key negotiates without a user id, since every revocable join gate needs the key. - ISignalRNotificationService.DisconnectUserAsync takes the tenant and the key. LiveStreamRevoker is its only caller and names the tenant each grant resolved under: member routes the route's tenant, self-service routes the managing tenant, Global Admin routes the tenant of the UPN's identity binding. Replacing or deleting a binding now cuts the streams signed in under the previous one. - A self-service assignment confers scope only while its assignee is bound to the owning tenant, so a self-service grant resolves under the owner alone and the owner's revokes never need another tenant. - Remove, disable and enable of a UPN without a row in the tenant answer 404 and change nothing: no audit, no push revoke, no end of an assignment, no cut. - GlobalAdminService.DisableGlobalAdminAsync and its repository method had no caller and are removed. - Tests pin the finding's attack, the 404s, the self-service gate, the binding routes and the call sites; each part was mutated back to the old behaviour and failed its tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>