Bug 2527214 (CVE-2026-84720) - CVE-2026-84720 automation-controller: automation-controller: WorkflowJobNode.ancestor_artifacts lacks prevent_search, exposing no_log set_stats artifacts via ORM-traversal count-oracle
Summary: CVE-2026-84720 automation-controller: automation-controller: WorkflowJobNode....
Keywords:
Status: NEW
Alias: CVE-2026-84720
Deadline: 2026-10-01
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-09-02 01:34 UTC by OSIDB Bzimport
Modified: 2026-09-23 21:08 UTC (History)
8 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2026:71113 0 None None None 2026-09-23 20:51:35 UTC
Red Hat Product Errata RHSA-2026:71114 0 None None None 2026-09-23 21:08:11 UTC

Description OSIDB Bzimport 2026-09-02 01:34:23 UTC
A flaw was found in the Ansible Automation Platform automation-controller workflow subsystem.
WorkflowJobNode.ancestor_artifacts (awx/main/models/workflow.py:262-266) is a JSONBlob column
that the workflow task-manager fills with the raw merged set_stats artifacts of every upstream
node's job (get_effective_artifacts) and, for child workflows, with the parent workflow's
aggregated artifacts (seed_root_ancestor_artifacts, workflow.py:743-753). The field is
deliberately omitted from WorkflowJobNodeSerializer and Ansible's _ansible_no_log flag is honored
only after the raw dict has been persisted: in get_job_kwargs (workflow.py:352-370) the
aggregated artifacts are assigned and saved at lines 360-361, and only afterwards (lines 363-370)
are the no_log keys copied into the child job's survey_passwords mask, leaving the
ancestor_artifacts column itself unredacted. Because the field is not wrapped in prevent_search(),
the django-ansible-base FieldLookupBackend admits arbitrary __contains/__regex/__startswith
lookups against it. A principal with read_role on the WorkflowJob can issue
GET /api/controller/v2/workflow_job_nodes/?id=<n>&ancestor_artifacts__contains=<probe> and use
the response count as a boolean oracle to recover the full JSON of the hidden column, including
values protected with set_stats no_log. In addition, because the credential-types list endpoint
is readable by any authenticated user (CredentialTypeAccess.filtered_queryset returns all
objects), and because a regular-expression lookup bypasses the JSONField cross-relation guard
that rejects __icontains, a user with no roles can reach the same column across all organizations
via GET /api/controller/v2/credential_types/?credentials__workflowjobnodes__ancestor_artifacts__
regex=<probe> whenever a workflow node carries a prompted credential. This defeats both the
serializer-level omission of the field and Ansible's no_log artifact-masking control, and enables
cross-tenant recovery of secrets passed between workflow stages via set_stats. This is a variant,
on a previously unreported adjacent field, of the earlier Job/JobEvent artifact and stdout
prevent_search gaps.

Comment 2 Jon Orris 2026-09-23 20:51:34 UTC
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

Comment 3 Jon Orris 2026-09-23 21:08:10 UTC
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


Note You need to log in before you can comment on or make changes to this bug.