Bug 2527220 (CVE-2026-84721) - CVE-2026-84721 automation-controller: automation-controller: Email notification backend allows SSRF via user-controlled SMTP host/port (internal port-scan oracle, SMTP password exfil)
Summary: CVE-2026-84721 automation-controller: automation-controller: Email notificati...
Keywords:
Status: NEW
Alias: CVE-2026-84721
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:46 UTC by OSIDB Bzimport
Modified: 2026-09-23 19:13 UTC (History)
8 users (show)

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


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-09-02 01:46:02 UTC
A flaw was found in the Ansible Automation Platform automation-controller notification subsystem.
CustomEmailBackend (awx/main/notifications/email_backend.py:24) is a thin subclass of
django.core.mail.backends.smtp.EmailBackend and does not override open()/send_messages() to
validate its connect target, so the user-controlled notification_configuration.host and .port
reach smtplib.SMTP(host, port, timeout=...) with no allow-list and no private/loopback/
link-local/reserved rejection. An organization-scoped Notification Admin
(awx.notification_admin_role, checked by NotificationTemplateAccess.can_add/can_change at
awx/main/access.py:2578/2582 — a delegatable, non-superuser role) can create or PATCH an email
notification template with host/port pointing at any internal address and POST the template's
/test/ endpoint. The dispatcher runs the backend on the controller-task pod, which opens a raw
TCP connection to the attacker-chosen host:port. The smtplib exception string is persisted
verbatim into Notification.error (a plain TextField, awx/main/models/notifications.py:219) and is
readable over the API, producing a three-state oracle: "[Errno 111] Connection refused" (closed),
"timed out" (filtered), and "Connection unexpectedly closed: timed out" or an SMTPResponseException
(open). Because the transport is a raw socket, the flaw reaches non-HTTP internal services (for
example Redis, PostgreSQL, receptor) and the in-cluster Kubernetes API, and can send SMTP-protocol
bytes into those listeners. In addition, the SMTP AUTH exchange transmits the template's stored,
otherwise write-only password to the configured host, so a user who can change the host on a
shared organization template can exfiltrate its stored SMTP password. The HTTP-based notification
backends (webhook, grafana, mattermost, rocketchat) were hardened against this on the 2.7 branch
via awx/main/notifications/url_validation.py::validate_url(); the email backend (and the IRC
backend) were omitted from that hardening. That guard is present only on the 2.7 branch; on the
2.5, 2.6, and development branches it is absent and no notification backend validates its connect
target.

    Upstream: https://github.com/ansible/tower (awx)
    Affected file: awx/main/notifications/email_backend.py:24 (CustomEmailBackend, no
                   host validation); awx/main/models/notifications.py:219 (Notification.error
                   oracle sink); awx/main/access.py:2559-2582 (notification_admin_role).
                   Guard (2.7 only): awx/main/notifications/url_validation.py::validate_url
                   (added by tower #7875).


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