Bug 2511903 (CVE-2026-71367)

Summary: CVE-2026-71367 awx: WebSocket broadcast groups leak cross-organization job metadata
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: dschmidt, jlanda, kshier, rbobbitt, security-response-team, simaishi, stcannon, teagle, yguenane
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
An incorrect authorization vulnerability was found in AWX's WebSocket consumer. The consumer_access() function only enforces access controls for object-level event groups (job_events, workflow_events, ad_hoc_command_events) but does not restrict subscriptions to global broadcast groups such as 'jobs-status_changed'. When an authenticated user subscribes to a global broadcast group, the server accepts the subscription without verifying that the user has permission to view the associated resources. In multi-organization deployments, this allows a low-privilege user in one organization to receive real-time job status metadata from all organizations, including job IDs, status transitions, timestamps, and infrastructure topology details such as instance group names, bypassing the organization isolation enforced by the REST API.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-08-06 04:59:45 UTC
AWX WebSocket subscriptions skip RBAC checks for global broadcast groups. The consumer_access() function in awx/main/access.py maps only object-level event groups to access classes:

class_map = {
    'job_events': JobAccess,
    'workflow_events': WorkflowJobAccess,
    'ad_hoc_command_events': AdHocCommandAccess,
}
return class_map.get(group_name)

When a client subscribes to a broadcast group such as 'jobs-status_changed', group_name is 'jobs', so consumer_access() returns None. The consumer in awx/main/consumers.py only runs user_can_see_object_id() when the access class is not None; otherwise it adds the user to the requested group unconditionally:

access_cls = consumer_access(group_name)
if access_cls is not None:
    if not await self.user_can_see_object_id(user_access, oid):
        continue
new_groups.add(name)

The job model emits global status updates to 'jobs-status_changed' including job IDs, status changes, timestamps, and instance_group_name. In multi-organization deployments, a low-privilege user from one organization can receive real-time status metadata for jobs in all organizations that are otherwise hidden by the REST API.