CVE-2021-39937
Description
A collision in access memoization logic in all versions of GitLab CE/EE before 14.3.6, all versions starting from 14.4 before 14.4.4, all versions starting from 14.5 before 14.5.2, leads to potential elevated privileges in groups and projects under rare circumstances
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A collision in GitLab's access memoization logic can cause incorrect privilege elevation for groups and projects when IDs collide.
Vulnerability
The BulkMemberAccessLoad concern in GitLab CE/EE (all versions before 14.3.6, 14.4.0-14.4.3, 14.5.0-14.5.1) uses a memoization key "max_member_access_for_#{klass.name.underscore.pluralize}:#{memoization_index}" that does not differentiate between project and group IDs. When a project and a group share the same numeric ID, the cached access level for one can be incorrectly returned for the other within the same request [1].
Exploitation
An attacker would need to be able to trigger a request that queries both a group and a project with the same ID. This could occur via GraphQL multiplexing or other API endpoints that evaluate access for multiple resources. The attacker must have some level of access to one of the resources (e.g., maintainer on a group) to cause the memoization of that access level, which then incorrectly applies to the other resource (e.g., a project with the same ID) if the attacker has no or lower access there [1].
Impact
Successful exploitation could lead to elevated privileges, allowing an attacker to gain unauthorized access to groups or projects. The impact is limited to scenarios where ID collisions occur and the attacker has some access to one resource. The vulnerability could result in information disclosure or unauthorized actions depending on the privileges gained [1].
Mitigation
GitLab released fixes in versions 14.3.6, 14.4.4, and 14.5.2. Users should upgrade to these or later versions. No workaround is available. The fix differentiates memoization keys by model type [1].
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
3- Range: <14.3.6, >=14.4 <14.4.4, >=14.5 <14.5.2
- Range: >=0.0, <14.3.6
Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"The memoization key in BulkMemberAccessLoad does not differentiate between project and group IDs, causing cache collisions that return stale access levels."
Attack vector
An attacker can exploit a collision in the memoization cache used by `BulkMemberAccessLoad` [ref_id=1]. If a group with ID=6 grants the attacker `MAINTAINER` access, that result is cached under the key `max_member_access_for_users:6` [ref_id=1]. On the same request, if the attacker then queries a project with ID=6 to which they have no access, the cached value `MAINTAINER` is returned without a database lookup, granting elevated privileges [ref_id=1]. The reverse scenario also applies: a cached "no access" result for a project can incorrectly deny access to a group sharing the same ID [ref_id=1]. The advisory notes this is likely exploitable via the GraphQL API using multiplexed queries [ref_id=1].
Affected code
The vulnerability resides in the `BulkMemberAccessLoad` concern, specifically in the memoization key construction at [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/64ada62a60172dff2c70a2c9636492651e8e7d1c/app/models/concerns/bulk_member_access_load.rb#L45) [ref_id=1]. The key is built as `"max_member_access_for_#{klass.name.underscore.pluralize}:#{memoization_index}"`, but `memoization_index` does not differentiate whether the stored ID belongs to a project or a group [ref_id=1].
What the fix does
The advisory recommends changing the memoization key on [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/64ada62a60172dff2c70a2c9636492651e8e7d1c/app/models/concerns/bulk_member_access_load.rb#L45) to include the model type as part of the key, so that a project ID and a group ID with the same numeric value are stored under distinct cache entries [ref_id=1]. No patch diff is provided in the bundle, but the suggested fix would prevent the collision by ensuring the cache key differentiates between models [ref_id=1].
Preconditions
- inputThe attacker must be able to send a single request (e.g., a multiplexed GraphQL query) that triggers access checks for both a group and a project that share the same numeric ID.
- authThe attacker must have at least some level of access to one of the colliding resources (group or project) to seed the memoization cache with a privilege level.
Generated on May 25, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2- gitlab.com/gitlab-org/cves/-/blob/master/2021/CVE-2021-39937.jsonmitrex_refsource_CONFIRM
- gitlab.com/gitlab-org/gitlab/-/issues/336802mitrex_refsource_MISC
News mentions
0No linked articles in our index yet.