Bug 2533037 (CVE-2026-90959)

Summary: CVE-2026-90959 pulpcore: pulpcore: file:// scheme allowlist bypass in content upload file_url field enables arbitrary file read and Pulp Container registry signing key theft
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: anthomas, dranck, dschmidt, ehelms, ggainey, jlanda, jmitchel, jpasqual, juwatts, kshier, lbrazdil, mdellweg, mhulan, mminar, nmoumoul, osousa, pcreech, rbiba, rchan, security-response-team, simaishi, smallamp, sskracic, stcannon, teagle, tmalecek, tpfromme, yguenane
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A path traversal vulnerability was found in pulpcore. The content upload API accepts a 'file_url' parameter that allows users with file repository privileges to specify a local file URL for Pulp to download and store. A URL scheme validation check uses a string prefix comparison that only rejects URLs beginning with 'file://', but Python's URL parser recognizes the 'file:' scheme without double slashes, creating a mismatch between what is validated and what is dispatched to the file downloader. An authenticated user with low-privilege repository permissions can supply a specially crafted URL using relative path traversal sequences to read any file accessible to the Pulp server process. In deployments that include Pulp Container, successful exploitation allows an attacker to read the container registry token signing private key and forge bearer tokens, granting unauthorized access to all private container repositories in the affected registry.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-09-14 13:15:06 UTC
Pulpcore provides a content upload API field 'file_url' that allows any authenticated user with repository creator privileges to supply a URL from which Pulp will download and store content as an Artifact. The validator for this field (validate_url in RemoteSerializer, pulpcore/app/serializers/repository.py line 139) checks file paths ONLY when the URL string begins with 'file://' (using a case-insensitive startswith check). The DownloaderFactory (pulpcore/download/factory.py line 181) dispatches on the parsed URL scheme using Python's urlparse(), which correctly identifies 'file:../../path' (single colon, no double slash) as having scheme 'file'. This creates a validator/dispatcher mismatch: a URL like 'file:../../../../../../etc/pulp/certs/token_private_key.pem' passes the string-based allowlist check (it does not start with 'file://') and is dispatched to FileDownloader. FileDownloader also calls RemoteSerializer().validate_url() which performs the same incomplete string check. The resolved path is computed as os.path.abspath(os.path.join(p.netloc, p.path)) where p.netloc is empty and p.path is the relative traversal sequence, making the final path relative to the Pulp process's working directory. The file is read and stored as an Artifact, then served through a File Distribution.

The reporter (Yonghwa Lee, Xint by Theori, underdog) demonstrated end-to-end exploitation: a non-staff non-superuser holding only file.filerepository_creator and file.filedistribution_creator roles successfully reads /etc/pulp/certs/token_private_key.pem (the Pulp Container registry JWT signing key at its documented default path), publishes it through their own distribution, downloads it, forges ES256 JWT bearer tokens, and performs unauthorized pull, push, persistence, and manifest deletion on private container repositories belonging to other users. Five independent trials confirmed this in the reporter's lab (results.txt included in PULP-001-artifact.zip).

Affected versions: pulpcore 3.117.1 and pulp-container 2.29.0 confirmed; current main branch also affected. No upstream fix is available at the time of ticket creation.

PSIRT Ticket: PSIRTSUPT-23758