Bug 2533037 (CVE-2026-90959) - 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
Summary: CVE-2026-90959 pulpcore: pulpcore: file:// scheme allowlist bypass in content...
Keywords:
Status: NEW
Alias: CVE-2026-90959
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-09-14 13:15 UTC by OSIDB Bzimport
Modified: 2026-09-24 14:30 UTC (History)
28 users (show)

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


Attachments (Terms of Use)

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


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