Fedora Account System
Red Hat Associate
Red Hat Customer
galaxy_ng is a Pulp plugin powering Ansible Galaxy and Ansible Automation Platform Private Automation Hub. A server-side request forgery (SSRF) exists in the namespace avatar download path. In galaxy_ng/app/api/v3/serializers/namespace.py, avatar_url is a DRF URLField. That field validates URL syntax and scheme (http/https) only. It does not resolve the hostname or filter private, loopback, link-local, or cloud-metadata addresses. On namespace create, download_logo is always True. On update, download_logo is True whenever avatar_url is present. The serializer then dispatches a Pulp task that calls _download_avatar() in galaxy_ng/app/tasks/namespaces.py. _download_avatar() builds an aiohttp session with ClientTimeout(total=None, sock_connect=600, sock_read=600) and passes the user-supplied URL to pulpcore HttpDownloader with no address restriction and no redirect-target revalidation. The Pulp worker therefore requests whatever address the publisher supplied, including RFC1918, 127.0.0.0/8, 169.254.0.0/16, and cloud metadata endpoints. The SSRF is blind: the response is stored only if it passes image validation (PIL ImageField or SVG). Non-image bodies are discarded, so this is not direct credential exfiltration. The attacker still gets a binary oracle via namespace avatar_sha256 (updated vs unchanged), which is enough to enumerate reachable internal IPs and ports from the worker's network. The total=None timeout also lets a slow or hanging target pin a worker, which is a denial-of-service angle. Privilege required is an authenticated user with galaxy.change_namespace or galaxy.add_namespace. In community Galaxy that includes a user's own namespace. Affected: galaxy_ng (verified on current main, HEAD 2bc7189 at clone time). No upstream fix identified in the examined tree. Reporter: Arpit Jain (GitHub arpitjain099), independent security researcher. PSIRT ticket: PSIRTSUPT-22101 Distinct from GHSA-hc3x-6pf5-pmj3 (legacy role import path).