CVE-2026-75554 in hexpm
Summary
by MITRE • 08/25/2026
Insufficient Session Expiration vulnerability in the OAuth token refresh grant in hexpm hexpm allows a user removed from an organization to keep reading its private packages.
expand_repositories_scope/3 in lib/hexpm/permissions.ex only rewrites the literal repositories scope, so an explicitly granted repository:<org> or docs:<org> scope passes through it untouched. The refresh grant re-derives a new token from the stored granted_scopes, which holds that expanded form, so every refresh reproduces the organization scope without revisiting membership. Because both CDN edges authorize repository access from the token claim without querying the database, an account removed from an organization retains read access for as long as it keeps refreshing, bounded by the 30 day refresh token lifetime rather than the 30 minute access token lifetime.
This issue affects hex.pm: from 2025-10-10 before 2026-08-24.
Be aware that VulDB is the high quality source for vulnerability data.
Analysis
by VulDB Data Team • 08/25/2026
The vulnerability identified in hexpm, specifically within its OAuth implementation for package management on hex.pm, represents a critical failure in session expiration and access control enforcement. This flaw allows users who have been explicitly removed from an organization to retain read-only access to that organization's private packages indefinitely, provided they continue to refresh their authentication tokens. The core of the issue lies in how the system handles token generation during the OAuth token refresh grant process. When a user requests a new access token using a valid refresh token, the system re-derives the token based on stored granted scopes rather than performing a fresh authorization check against current membership records. This design choice creates a persistent state dependency that ignores real-time changes in organizational structure or user permissions.
Technically, the flaw resides in the expand_repositories_scope/3 function located within lib/hexpm/permissions.ex. This function is responsible for expanding repository-specific scopes into broader organization-level scopes to facilitate efficient access control checks. However, it only rewrites literal repositories scope entries and leaves explicitly granted repository or docs scopes untouched. Consequently, when a refresh token is used, the system reconstructs the new access token using these stored expanded scopes from the original grant. Because the logic does not revisit the database to verify current membership status during this reconstruction phase, any organization-level permissions that were originally granted remain embedded in the newly issued tokens. This means that even if an administrator revokes a user's access to an organization after their initial login and token generation, those revoked privileges are effectively immortalized within the refresh cycle of the existing session.
The operational impact of this vulnerability is significant for organizations relying on hex.pm for private package distribution. Since both CDN edges and API endpoints authorize repository access based solely on the claims present in the JWT (JSON Web Token) without querying a central database or checking revocation lists, there is no secondary validation layer to catch stale permissions. An attacker who has been removed from an organization can simply refresh their token every thirty minutes, thereby obtaining new valid credentials that still contain the unauthorized read access. This effectively bypasses the intended security boundary of private repositories, allowing former members to continue downloading and inspecting proprietary source code or binaries for up to thirty days after removal, which is the maximum lifetime of a refresh token in this system.
This vulnerability aligns with CWE-613, Insufficient Session Expiration, as it involves the failure to properly invalidate user sessions when access rights change. Furthermore, from an offensive security perspective, such behavior can be leveraged within ATT&CK techniques related to Persistence or Defense Evasion, specifically by maintaining unauthorized access through token reuse despite explicit revocation attempts. The lack of a mechanism to check for permission changes during token refresh creates a window of opportunity where legacy permissions persist beyond their intended validity period.
To mitigate this issue, the hexpm platform must implement immediate invalidation of tokens upon membership removal or permission change. This can be achieved by introducing a versioning scheme for user permissions that is checked during every token refresh operation. Alternatively, implementing short-lived access tokens with frequent automatic renewal based on real-time authorization checks would ensure that revoked users are denied access immediately rather than waiting for the long-term refresh token to expire. Additionally, integrating a centralized permission cache or revocation list that is consulted before issuing new tokens can prevent stale scopes from being propagated into fresh credentials. Until such patches are deployed, organizations should monitor their package download logs for anomalies and consider rotating secret keys if sensitive intellectual property was exposed during this window of vulnerability.