CVE-2026-27838 Overview
CVE-2026-27838 is an Insecure Direct Object Reference (IDOR) vulnerability in wger, a free, open-source workout and fitness manager application. The vulnerability exists in five routine detail action endpoints that check a cache before calling self.get_object(). In versions up to and including 2.4, cache keys are scoped only by pk (primary key) without including any user ID, allowing attackers to access cached routine data belonging to other users.
Critical Impact
An authenticated attacker can retrieve cached workout routine data from other users by accessing API endpoints with valid routine primary keys, bypassing ownership validation checks.
Affected Products
- wger Workout Manager versions up to and including 2.4
Discovery Timeline
- 2026-02-26 - CVE CVE-2026-27838 published to NVD
- 2026-02-26 - Last updated in NVD database
Technical Details for CVE-2026-27838
Vulnerability Analysis
This vulnerability is classified under CWE-639 (Authorization Bypass Through User-Controlled Key), which occurs when the application uses user-controlled data as a key to access records belonging to other users. The wger application implements caching for API performance optimization on routine detail endpoints. However, the cache key generation mechanism only incorporates the routine's primary key (pk) value without including the requesting user's identifier.
When a legitimate user accesses their routine via the API, the response is cached using a key based solely on the routine's pk. Subsequently, any authenticated user who knows or guesses a valid routine pk can retrieve the cached response for that routine, completely bypassing the ownership verification that would normally occur in self.get_object(). This allows unauthorized access to sensitive workout and fitness data belonging to other users.
Root Cause
The root cause of this vulnerability lies in improper cache key scoping within the CacheKeyMapper class methods. The cache key generation functions (routine_api_date_sequence_display_key, routine_api_date_sequence_gym_key, routine_api_stats, routine_api_structure_key, and routine_api_logs) were designed to use only the routine pk as a unique identifier. This design assumed that the authorization check in self.get_object() would always execute, but the caching mechanism returns data before this check can occur.
Attack Vector
The attack requires network access and authentication with low-privilege credentials. An attacker must:
- Authenticate to the wger application with any valid user account
- Enumerate or guess valid routine primary key values
- Request API endpoints for routines with those pk values
- Receive cached responses containing other users' routine data if those users previously accessed the same endpoints
The vulnerability requires high attack complexity because the target user must have previously accessed their routine via the API (to populate the cache), and the cache entry must still be valid when the attacker makes their request.
"""
Return the day sequence of the routine
"""
- # profiler = cProfile.Profile()
- # profiler.enable()
-
- cache_key = CacheKeyMapper.routine_api_date_sequence_display_key(pk)
+ cache_key = CacheKeyMapper.routine_api_date_sequence_display_key(pk, request.user.id)
cached_data = cache.get(cache_key)
if cached_data is not None:
return Response(cached_data)
Source: GitHub Commit Overview
"""Resets all caches related to a routine"""
cache.delete(CacheKeyMapper.routine_date_sequence_key(instance.id))
- cache.delete(CacheKeyMapper.routine_api_date_sequence_display_key(instance.id))
- cache.delete(CacheKeyMapper.routine_api_date_sequence_gym_key(instance.id))
- cache.delete(CacheKeyMapper.routine_api_stats(instance.id))
+ cache.delete(CacheKeyMapper.routine_api_date_sequence_display_key(instance.id, instance.user_id))
+ cache.delete(CacheKeyMapper.routine_api_date_sequence_gym_key(instance.id, instance.user_id))
+ cache.delete(CacheKeyMapper.routine_api_logs(instance.id, instance.user_id))
+ cache.delete(CacheKeyMapper.routine_api_stats(instance.id, instance.user_id))
if structure:
- cache.delete(CacheKeyMapper.routine_api_structure_key(instance.id))
+ cache.delete(CacheKeyMapper.routine_api_structure_key(instance.id, instance.user_id))
if instance.pk:
for day in instance.days.all():
Source: GitHub Commit Overview
Detection Methods for CVE-2026-27838
Indicators of Compromise
- Unusual API access patterns where a single user requests routine endpoints with sequential or incremental pk values
- Access logs showing successful retrieval of routine data for pk values not owned by the requesting user
- Rapid enumeration attempts against routine API endpoints from authenticated sessions
Detection Strategies
- Implement logging that correlates routine pk values with the authenticated user's owned routines
- Monitor for API requests where the requested routine pk does not belong to the authenticated user
- Alert on patterns indicative of enumeration attacks against routine endpoints
Monitoring Recommendations
- Enable detailed access logging for all routine API endpoints (/api/v2/routine/ paths)
- Implement rate limiting on routine API endpoints to slow enumeration attempts
- Configure alerts for cache hit patterns that indicate cross-user data access
How to Mitigate CVE-2026-27838
Immediate Actions Required
- Upgrade wger to a version containing commit e964328784e2ee2830a1991d69fadbce86ac9fbf or later
- Clear all existing routine-related caches to remove potentially exploitable cached data
- Review access logs for signs of exploitation before applying the patch
Patch Information
The vulnerability has been addressed in commit e964328784e2ee2830a1991d69fadbce86ac9fbf. The fix modifies the cache key generation to include the user_id parameter alongside the routine pk, ensuring that cache keys are unique per user-routine combination. This prevents one user's cached data from being served to another user. For detailed patch information, refer to the GitHub Security Advisory GHSA-42cr-w2gr-m54q.
Workarounds
- Disable caching for routine API endpoints entirely until the patch can be applied
- Implement an additional authorization layer at the web server or reverse proxy level
- Restrict API access to trusted networks or users until remediation is complete
# Configuration example - Clear wger cache (if using Redis)
redis-cli KEYS "*routine*" | xargs redis-cli DEL
# Or for Django cache framework
python manage.py shell -c "from django.core.cache import cache; cache.clear()"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


