CVE-2026-54723 Overview
CVE-2026-54723 affects devpi-server, a Python package index staging server used for packaging, testing, and release workflows. The vulnerability allows an unauthenticated attacker to send a modified GET request to the +changelog route on servers configured with the primary or deprecated master role. The verify_primary function fails to reject requests missing an identity, bypassing the required ReplicaIdentity check. Successful exploitation discloses complete database content, including Argon2 password hashes and devpi-token identifiers with salts. Large responses can also consume significant CPU, I/O, and bandwidth on the target server.
Critical Impact
Unauthenticated network attackers can extract the full devpi database, including Argon2 password hashes and token material, from any primary-role server exposed without devpi-lockdown.
Affected Products
- devpi-server versions prior to 6.20.2
- devpi-server 7.0.0 pre-release versions prior to 7.0.0b3
- Deployments configured with the primary or deprecated master role
Discovery Timeline
- 2026-09-14 - CVE-2026-54723 published to the National Vulnerability Database (NVD)
- 2026-09-14 - Last updated in NVD database
Technical Details for CVE-2026-54723
Vulnerability Analysis
The flaw is an improper authentication weakness classified under [CWE-304] (Missing Critical Step in Authentication). The +changelog endpoint on primary-role devpi servers is designed exclusively for replica synchronization and should only respond to authenticated replicas presenting a ReplicaIdentity.
The verify_primary function contained a logic error that permitted requests with no identity at all to pass validation. Only requests carrying an authenticated non-replica identity were rejected. This gap allowed anonymous clients to read the changelog stream and reconstruct database state.
Disclosed material includes stored Argon2 password hashes, which are subject to offline dictionary attacks, and public identifiers plus salts for devpi-tokens, which may assist attackers attempting to derive the server secret. Replaying large +changelog/{serial} requests also produces resource exhaustion on the primary.
Root Cause
The pre-patch logic evaluated the identity as if identity is not None and not isinstance(identity, ReplicaIdentity). When identity was None, both conditions short-circuited and the function returned without raising HTTPForbidden. The check should have unconditionally required a ReplicaIdentity instance.
Attack Vector
An unauthenticated remote attacker sends a crafted GET request to /+changelog/{serial} on an exposed primary-role devpi-server. No credentials, user interaction, or prior access are required. Standalone-role instances are not exposed through replication. Instances fronted exclusively by nginx with devpi-lockdown redirect the request to login and have no known exploit path.
"expected %s as primary_uuid, replica sent %s" %
(primary_uuid, expected_uuid))
- identity = self.request.identity
- if identity is not None and not isinstance(identity, ReplicaIdentity):
- raise HTTPForbidden(
- "Authenticated identity '%r' isn't from replica." % identity)
+ if not isinstance(self.request.identity, ReplicaIdentity):
+ raise HTTPForbidden("Replication endpoint requires a replica identity.")
@view_config(route_name="/+changelog/{serial}")
def get_changes(self):
Source: GitHub Commit b4ea49fed4. The patch removes the flawed None short-circuit and requires that every request to the replication endpoint present a valid ReplicaIdentity.
Detection Methods for CVE-2026-54723
Indicators of Compromise
- Unauthenticated HTTP GET requests to /+changelog/{serial} in devpi-server access logs originating from non-replica source addresses.
- Unusually large response bodies served from the +changelog route to clients outside the known replica pool.
- Sustained bandwidth or CPU spikes on the primary-role devpi-server correlated with sequential serial values.
Detection Strategies
- Compare source IPs hitting +changelog against the allowlist of provisioned replica hosts and alert on any mismatch.
- Inspect request logs for +changelog traffic that lacks the X-DEVPI-UUID or replica authentication headers.
- Baseline outbound response volume from the primary and flag deviations that suggest bulk changelog scraping.
Monitoring Recommendations
- Forward devpi-server access and error logs to a centralized SIEM or data lake for query and correlation.
- Track authentication failures and HTTPForbidden responses on replication endpoints post-patch to confirm enforcement.
- Monitor for offline password cracking indicators, such as reused credentials appearing in downstream authentication systems.
How to Mitigate CVE-2026-54723
Immediate Actions Required
- Upgrade devpi-server to version 6.20.2 or 7.0.0b3 on all instances running the primary or deprecated master role.
- Rotate the server secret and invalidate any devpi-tokens issued before the upgrade.
- Force password resets for all user accounts to invalidate potentially disclosed Argon2 hashes.
Patch Information
The fix is available in GitHub Release server-6.20.2 and the 7.0.0b3 pre-release. Full advisory details are published as GHSA-m5pq-69xg-vcq3. The patch enforces that all requests to the replication endpoint present a valid ReplicaIdentity.
Workarounds
- Front the devpi-server exclusively with nginx and enable devpi-lockdown, which redirects unauthenticated requests to the login flow.
- Restrict network access to the +changelog route using firewall or reverse-proxy rules that only permit known replica IP addresses.
- Where feasible, convert primary-role servers with no active replicas to the standalone role, which does not expose the replication endpoint.
# nginx location restriction limiting /+changelog to known replica hosts
location ~ ^/\+changelog/ {
allow 10.0.0.11; # replica-1
allow 10.0.0.12; # replica-2
deny all;
proxy_pass http://devpi_primary;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

