Where
-Infinity
0
Severity
4.3
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N

A flaw was found in the Ansible Automation Platform automation-controller request handling. The shipped production settings define REMOTEHOSTHEADERS=['HTTPXFORWARDEDFOR'] and PROXYIPALLOWEDLIST=[] (empty). In APIView.initializerequest (awx/api/generics.py:199-201), client-supplied REMOTEHOSTHEADERS are stripped only when PROXYIPALLOWEDLIST is non-empty and the request did not arrive through a listed proxy; with the empty shipped allow-list this guard is skipped and the X-Forwarded-For header is never stripped. When the client IP is resolved via getremotehost()/getremotehosts() (django-ansible-base ansiblebase/lib/utils/requests.py), the function reads REMOTEHOSTHEADERS in order and returns the first (leftmost) X-Forwarded-For entry. Because the deployment fronts Controller with Envoy, which by default appends (rather than replaces) the real client IP to the incoming X-Forwarded-For header, an attacker-supplied leftmost value survives to the application and is chosen as the client IP. That spoofed value is written into the Controller's audit/access logging, including the login audit message ("User <username> logged in from <ip>") and the API 4xx error log's remoteaddr field (API400ERRORLOGFORMAT). An attacker can therefore forge the source IP attributed to API actions in Controller logs and any downstream SIEM keyed on client IP. Unauthenticated failed-login and error log entries can likewise be attributed to arbitrary IPs. A secure mechanism already exists but is not enabled by default: when a valid HTTPXTRUSTEDPROXY shared-secret header is present, getremotehosts prefers the trusted last/rightmost X-Forwarded-For entry (the value Envoy appends) and honors x-envoy-external-address. The flaw affects only audit/forensic integrity and does not grant additional access.

Upstream: https://github.com/ansible/tower (awx) and https://github.com/ansible/django-ansible-base (getremotehost[s]) Affected file: awx/api/generics.py:199-201 (guard), :119 and :246-265 (sinks); awx/settings/productiondefaults.py:23; awx/settings/defaults.py:166; ansiblebase/lib/utils/requests.py:14-16,38-42,65-66

1 / 2
Source: Red Hat
First published (updated )

A flaw was found in automation-controller (AWX). Project.scmbranch (awx/main/models/credential path awx/main/models/projects.py:98-111, a CharField with no validators) and scmrefspec are accepted as free text with no rejection of a leading dash (no validatescmbranch/validatescmrefspec and no leading-dash guard anywhere in awx/api/serializers.py, awx/main, or awx/playbooks). During project sync, RunProjectUpdate.buildextravarsfile (awx/main/tasks/jobs.py:1481-1518) copies scmbranch (:1486/:1508) and scmrefspec (:1517-1518) verbatim into the project-update extravars, and awx/playbooks/projectupdate.yml (- hosts: localhost, connection: local, :28-30) passes them to the ansible.builtin.git module as version: "{{ scmbranch | quote }}" (:50) and refspec: "{{ scmrefspec | default(omit) }}" (:51). The git module's switchversion() builds [/usr/bin/git, checkout, --force, <version>] with no -- end-of-options sentinel (upstream lib/ansible/modules/git.py), so a value beginning with -- is parsed by git as an option flag. The | quote filter is ansible's shlex.quote and does NOT defend against this: an all-shell-safe string such as --pathspec-from-file=/etc/passwd is returned unchanged (matching the live proof, whose command line shows no quotes). Setting scmbranch to --pathspec-from-file=/var/run/secrets/kubernetes.io/serviceaccount/token makes git read the file line-by-line as pathspecs and echo each line on stderr as error: pathspec '<line>' did not match any file(s) known to git; ansible-runner captures stderr into the job event stream, returned via GET /api/controller/v2/projectupdates/{id}/stdout/?format=txt — an arbitrary-file-read oracle on the sync host. Because projectupdate.yml runs on localhost and, on the tested OpenShift Operator deployment, that host is the automation-controller-task control-plane pod (confirmed: the leaked token's pod name matches a control node in /api/controller/v2/ping/), the read reaches control-plane secrets: the system:serviceaccount:ansible-automation-platform:automation-controller JWT (pod/secret CRUD in the AAP namespace -> full platform takeover), /etc/tower/SECRETKEY (offline decryption of every stored Credential), and /etc/tower/conf.d/.py (PostgreSQL credentials). Any user able to create or edit a project (Organization projectadmin, or Project Admin on a single project) can trigger this on project create/edit auto-sync; system administrator is not required, and any org's admin reads secrets governing all tenants on the control plane. scmrefspec (fed to git fetch, no quote at all) is a second option-injection sink to fix together. On deployments where project updates run in an isolated execution environment without control-plane secrets, the primitive is limited to that context. Discovered internally (pentest-aap); verified live on AAP 2.7 / automation-controller 4.8.1; still present on devel (fix prepared, not merged) Upstream: github.com/ansible/awx (awx/main/models/projects.py scmbranch/scmrefspec; awx/api/serializers.py Project serializers; awx/main/tasks/jobs.py RunProjectUpdate.buildextravarsfile; awx/playbooks/projectupdate.yml) and github.com/ansible/ansible (ansible.builtin.git switchversion -- add --).

First published (updated )
Severity
6.6
AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:L/A:N

An improper authorization flaw exists in the Ansible Automation Controller. This flaw allows an attacker using the k8S API server to send an HTTP request with a service account token mounted via automountServiceAccountToken: true, resulting in privilege escalation to a service account.

1 / 2
Source: NVD
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203