Bug 2527075 (CVE-2026-84475)

Summary: CVE-2026-84475 automation-controller: automation-controller-container: automation-controller: InventorySource.source_vars lacks prevent_search, enabling zero-privilege cross-tenant extraction of inline inventory-plugin credentials via the credential_t ...
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: dschmidt, jlanda, kshier, 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:
automation-controller: InventorySource.source_vars lacks prevent_search, enabling zero-privilege cross-tenant extraction of inline inventory-plugin credentials via the credential_types FieldLookupBackend count-oracle
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:
Deadline: 2026-10-01   

Description OSIDB Bzimport 2026-09-01 20:35:17 UTC
A flaw was found in automation-controller (AWX). InventorySourceOptions.
source_vars (awx/main/models/inventory.py) is declared as a plain TextField
without a prevent_search() wrapper, unlike protected fields such as
CustomInventoryScript.script and Credential.inputs. django-ansible-base's
FieldLookupBackend permits __contains/__icontains/__startswith/__regex lookups
that traverse model joins without per-hop RBAC. Because the credential_types
list endpoint is readable by any authenticated user, an attacker holding zero
roles/organization/superuser/auditor privileges -- who is correctly denied on
the inventory_sources endpoints -- can query
credential_types?credentials__organization__inventories__inventory_sources__
source_vars__contains=<needle> (and the inventory_updates variant) and read
the result count as a boolean oracle (count>0 iff some tenant's source_vars
contains the needle). Using __regex the full plaintext is recovered
efficiently. source_vars is the documented location for inline dynamic-
inventory-plugin authentication (e.g. aws_access_key/aws_secret_key,
subscription_id/client_id/secret/tenant, username/password, token, api_key),
so the flaw discloses cross-tenant cloud-provider credentials to a zero-
privilege user. The field is defined on InventorySourceOptions and inherited
by InventorySource and InventoryUpdate. This is an instance of a broader class
in which unfiltered FieldLookupBackend joins on the globally-readable
credential_types list reach fields lacking prevent_search. Discovered
internally; verified live on AAP 2.7 / automation-controller 4.8.1.
    Upstream: github.com/ansible/awx (main/models/inventory.py) +
              django-ansible-base (FieldLookupBackend)