Fedora Account System
Red Hat Associate
Red Hat Customer
The API access classes for JobTemplate and WorkflowJobTemplate do not check the caller's Credential use_role when assigning the single-valued webhook_credential foreign key. The serializer checks only that this credential is a token for the selected webhook service. A user who may administer their own template and use its Project and Inventory appears able to attach a GitLab token credential that they are not allowed to use. The template's webhook key is available to that administrator. A GitLab webhook event then causes AWX to decrypt the attached token and send it in the PRIVATE-TOKEN header to the event-derived status URL. Confirmed in source for release tag 24.6.1 and devel commit 8565291e43e17cd1ee5333e82e57aeb230e6574e. Source-level root cause: (1) awx/api/permissions.py ModelAccessPermission.check_put_permissions delegates the PATCH authorization decision to JobTemplateAccess.can_change or WorkflowJobTemplateAccess.can_change. (2) awx/main/access.py JobTemplateAccess.can_add and can_change check the caller's permissions on the template, Project, Inventory and Execution Environment, but do not call check_related('webhook_credential', Credential, ..., role_field='use_role'); WorkflowJobTemplateAccess.can_change has the same omission, whereas UnifiedCredentialsMixin.can_attach enforces use_role for the normal many-to-many credentials relationship. (3) awx/api/serializers.py JobTemplateMixin.validate checks webhook_credential.credential_type.kind and namespace but not caller authorization for that Credential. (4) awx/api/views/webhooks.py WebhookKeyView.get returns a template's webhook key to its administrator; GitlabWebhookReceiver authenticates with that key then constructs a status URL from request.data['project']['web_url']; WebhookReceiverBase.post copies obj.webhook_credential and the status URL into the new job before signal_start. (5) awx/main/models/mixins.py WebhookMixin.update_webhook_status decrypts and sends the token. Reporter notes they verified the permission branch and outbound header construction by executing functions extracted from the official source snapshots and sent a dummy token to a loopback receiver through update_webhook_status; they did not deploy a full AWX instance.