For GitHub pullrequest webhooks, geteventstatusapi() in awx/api/views/webhooks.py returns pullrequest.statusesurl from the request body verbatim without any host validation:
def geteventstatusapi(self): if self.geteventtype() != 'pullrequest': return return self.request.data.get('pullrequest', {}).get('statusesurl')
The value is persisted into job extravars and later used by updatewebhookstatus() in awx/main/models/mixins.py:
statusapi = self.extravarsdict.get('awxwebhookstatusapi') headers = {k: v.format(self.webhookcredential.getinput('token')), 'Content-Type': 'application/json'} response = requests.post(statusapi, data=json.dumps(data), headers=headers, timeout=30)
There is no host allowlist for the expected Git provider endpoint and no private-network egress filtering before the request is sent. The webhook receiver relies on an HMAC secret (webhookkey), which is readable by users with the admin role on the job template via /api/v2/jobtemplates/{id}/webhookkey/. This allows a template admin to forge a signed webhook payload with statusesurl pointing to an attacker-controlled endpoint, and AWX will POST status updates including the Git PAT in the Authorization header to that endpoint.
A flaw was found in the AWX GitHub webhook integration. When a GitHub pullrequest webhook is received, GithubWebhookReceiver.geteventstatusapi() in awx/api/views/webhooks.py returns pullrequest.statusesurl from the request body without validation. The value is stored in job extra variables as awxwebhookstatusapi and later used by WebhookMixin.updatewebhookstatus() in awx/main/models/mixins.py as the callback URL when posting job status updates. If a job template is configured with webhookservice=github and a GitHub Personal Access Token credential as webhookcredential, the controller sends that token in the Authorization header when POSTing to the stored callback URL on job completion. Although the controller is designed to post commit status updates back to GitHub, it does not restrict the callback URL to trusted GitHub API endpoints. An attacker who can submit a forged webhook request with a valid HMAC-SHA1 signature for the target job template's webhookkey can supply an attacker-controlled statusesurl and cause exfiltration of the configured GitHub PAT when the triggered job completes. Normal GitHub webhook deliveries do not allow arbitrary contributors to control statusesurl; exploitation requires knowledge of the per-template webhook shared secret or privileged access to retrieve it from the controller. Upstream: https://github.com/ansible/awx Affected files: - awx/api/views/webhooks.py (GithubWebhookReceiver.geteventstatusapi) - awx/main/models/mixins.py (WebhookMixin.updatewebhookstatus)
A flaw was found in the AWX GitHub webhook integration. When a GitHub pullrequest webhook is received, GithubWebhookReceiver.geteventstatusapi() in awx/api/views/webhooks.py returns pullrequest.statusesurl from the request body without validation. The value is stored in job extra variables as awxwebhookstatusapi and later used by WebhookMixin.updatewebhookstatus() in awx/main/models/mixins.py as the callback URL when posting job status updates. If a job template is configured with webhookservice=github and a GitHub Personal Access Token credential as webhookcredential, the controller sends that token in the Authorization header when POSTing to the stored callback URL on job completion. Although the controller is designed to post commit status updates back to GitHub, it does not restrict the callback URL to trusted GitHub API endpoints. An attacker who can submit a forged webhook request with a valid HMAC-SHA1 signature for the target job template's webhookkey can supply an attacker-controlled statusesurl and cause exfiltration of the configured GitHub PAT when the triggered job completes. Normal GitHub webhook deliveries do not allow arbitrary contributors to control statusesurl; exploitation requires knowledge of the per-template webhook shared secret or privileged access to retrieve it from the controller. Upstream: https://github.com/ansible/awx Affected files: - awx/api/views/webhooks.py (GithubWebhookReceiver.geteventstatusapi) - awx/main/models/mixins.py (WebhookMixin.updatewebhookstatus)