- Shipped
- September 23, 2026 at 2:12 AM UTC
- Author
- Kamo
- Commit
- fbdc871
Three more of the same shape. - WebRTCSignalingController relayed **************** straight to **************** using only the payload's own sessionGuid, with nothing checked about the CONNECTED caller — **************** are exactly as client-controlled as the session guid itself. Every handler now refuses to relay unless the STOMP session's own memberId (stamped at CONNECT, never client-supplied) is a member of that session. The companion SUBSCRIBE-side gap in StompDestinationAuthz (/topic/webrtc/session/ and /topic/chat/session/ aren't guarded there) needs a change in WebSocketConfig.preSend, which this task explicitly reserved for a different agent fixing a logging finding in that file — left alone here to avoid the collision; flagging it for the coordinator. - **************** updateWebinarType, deleteWebinarType, addPresenter, updatePresenter, removePresenter, addReminder and removeReminder all checked MANAGE_SUPPORT in the caller's OWN org but never compared it to the id's actual owning org — a manager anywhere on the platform could edit, delete or restaff any other org's webinar catalogue by id. Added **************** reminderOwnerOrgId (same shape as the existing restrictionOwnerOrgId) and a denyIfNotOwn* check in the controller before every mutation. getScheduledWebinars(typeId) returned every attendee's name and email to any org eligible to book the type — which, for a parent-published type, can be several unrelated child orgs with nothing to do with each other; it now omits the roster (attendeeCount is all WebinarScheduleWizard.tsx ever rendered from it) rather than gating the endpoint itself, which would have broken that legitimate cross-org booking flow. cancelWebinar had no right check at all; now the assigned presenter or the booking org's own MANAGE_SUPPORT holder may cancel, nobody else. - **************** and CanvaRecipeController.save checked only that the caller was signed in to the org, matching neither's own Materials settings tab (MANAGE_MATERIALS, +MANAGE_SOCIAL_MEDIA once social targets are set). runAsMemberId was stored verbatim from the request body — any member id in any org — so a schedule could be made to run recurring Canva generation, and auto-post to the org's own social accounts, using a completely unrelated member's connected Canva token. Now validated against the caller's own organization, and CanvaScheduleSweep re-checks the same fact at run time in case a row predates the fix or a member later changes org. Tests: **************** WebinarCrossOrgOwnershipTest and **************** pin the new rules against the real controllers/services (MockMvc over a mocked service/AuthHelper, matching GamesEntitlementEndpointTest's own reasoning for why the gate itself must be real). Mutation verified: neutering the ownership check in updateWebinarType and the runAsMemberId org check each turned exactly the test built for it red. Full `mvn test` green before this commit.
