CVE-2026-84692 automation-controller: automation-controller-container: automation-controller: workflow job template node execute permission check bypassed by creating a node with a null unified_job_template and then patching it, allowing a single work ...
A flaw was found in Red Hat Ansible Automation Platform's automation-controller.
The execute-permission check on a workflow job template node's unified job
template is skipped when the node's currently stored unified job template is
empty: the check inspects only the existing value, not the incoming one, and a
node can be created without a unified job template. An authenticated user who
holds admin permission on a single workflow job template can create an empty node
and then patch it to reference any job template, project, inventory source,
system job, or workflow on the platform -- including ones in other organizations
that they cannot otherwise read or launch. Running their own workflow then
executes the victim template with the victim's attached credentials, inventory
and project, resulting in cross-organization privilege escalation to arbitrary
automation execution. The patch response also discloses the victim template's
name and description.
A flaw was found in automation-controller (AWX). In
WorkflowJobTemplateNodeAccess (awx/main/access.py), can_change() delegates the
execute-permission check on a node's unified_job_template to ujt_execute(), which
returns True unconditionally when the node's current obj.unified_job_template is
None, without ever validating the incoming data['unified_job_template'] against
execute_role. can_add() does not mark unified_job_template as mandatory, so a node
can be created with unified_job_template=null (HTTP 201). PATCHing that empty node
to any UnifiedJobTemplate id then succeeds (HTTP 200) with no execute_role check
on the new value. The direct-create path (POST a node with unified_job_template
set) is correctly denied (403) via can_add -> check_related(role_field=
'execute_role'); the create-empty-then-PATCH sequence bypasses that guard.
Consequently a user with admin_role on any single WorkflowJobTemplate (an
organization admin, an Organization Workflow Admin, or an object-level WFJT
admin) can bind and execute any Job Template, Project update, Inventory Source
sync, System Job Template, or nested Workflow Job Template belonging to any other
organization/tenant -- even ones for which direct GET/launch returns 403 --
running the victim template with the victim's attached credentials, inventory and
project. The PATCH response summary_fields additionally leaks the victim
template's name and description. Discovered internally (pentest-aap); verified
live on AAP 2.7 / automation-controller 4.8.x (victim WFJT executed end-to-end,
launched_by attacker); still present on devel.
Upstream: github.com/ansible/awx (awx/main/access.py:
WorkflowJobTemplateNodeAccess.ujt_execute / can_add / can_change;
check_related both-None handling).
This issue has been addressed in the following products:
Red Hat Ansible Automation Platform 2.6 for RHEL 10
Red Hat Ansible Automation Platform 2.6 for RHEL 9
Via RHSA-2026:71113 https://access.redhat.com/errata/RHSA-2026:71113
This issue has been addressed in the following products:
Red Hat Ansible Automation Platform 2.5 for RHEL 9
Red Hat Ansible Automation Platform 2.5 for RHEL 8
Via RHSA-2026:71114 https://access.redhat.com/errata/RHSA-2026:71114
A flaw was found in automation-controller (AWX). In WorkflowJobTemplateNodeAccess (awx/main/access.py), can_change() delegates the execute-permission check on a node's unified_job_template to ujt_execute(), which returns True unconditionally when the node's current obj.unified_job_template is None, without ever validating the incoming data['unified_job_template'] against execute_role. can_add() does not mark unified_job_template as mandatory, so a node can be created with unified_job_template=null (HTTP 201). PATCHing that empty node to any UnifiedJobTemplate id then succeeds (HTTP 200) with no execute_role check on the new value. The direct-create path (POST a node with unified_job_template set) is correctly denied (403) via can_add -> check_related(role_field= 'execute_role'); the create-empty-then-PATCH sequence bypasses that guard. Consequently a user with admin_role on any single WorkflowJobTemplate (an organization admin, an Organization Workflow Admin, or an object-level WFJT admin) can bind and execute any Job Template, Project update, Inventory Source sync, System Job Template, or nested Workflow Job Template belonging to any other organization/tenant -- even ones for which direct GET/launch returns 403 -- running the victim template with the victim's attached credentials, inventory and project. The PATCH response summary_fields additionally leaks the victim template's name and description. Discovered internally (pentest-aap); verified live on AAP 2.7 / automation-controller 4.8.x (victim WFJT executed end-to-end, launched_by attacker); still present on devel. Upstream: github.com/ansible/awx (awx/main/access.py: WorkflowJobTemplateNodeAccess.ujt_execute / can_add / can_change; check_related both-None handling).