id: PYSEC-2026-3418 published: "2026-07-13T14:36:39.533532Z" modified: "2026-07-13T16:07:32.741063Z" aliases: - CVE-2026-27838 - GHSA-42cr-w2gr-m54q summary: "wger: IDOR via user-unscoped cache keys on routine API actions exposes workout data" details: "### Summary\n\nFive routine detail action endpoints check a cache before calling `self.get_object()`. Cache keys are scoped only by `pk` — no user ID is included. When a victim has previously accessed their routine via the API, an attacker can retrieve the cached response for the same PK without any ownership check.\n\n### Details\n\n`wger/manager/api/views.py` — five actions follow this pattern (lines 134–201):\n\n```python\n@action(detail=True)\ndef date_sequence_display_mode(self, request, pk=None):\n cache_key = make_routine_api_date_sequence_display_cache_key(pk)\n cached = cache.get(cache_key)\n if cached:\n return Response(cached) # returned WITHOUT calling self.get_object()\n # only reaches ownership check on cache miss\n routine = self.get_object()\n ...\n```\n\nCache key construction in `wger/utils/cache.py:89–106`:\n\n```python\ndef make_routine_api_date_sequence_display_cache_key(routine_id):\n return f\"routine-api-date-sequence-display-{routine_id}\"\n # No user ID in key\n```\n\nCache TTL: 1 month (`4 * 604800` seconds, `settings_global.py:461`).\n\nAffected endpoints:\n```\nGET /api/v2/routine/{pk}/date-sequence-display/\nGET /api/v2/routine/{pk}/date-sequence-gym/\nGET /api/v2/routine/{pk}/structure/\nGET /api/v2/routine/{pk}/logs/\nGET /api/v2/routine/{pk}/stats/\n```\n\n### PoC\n\n```\n1. Victim (user A) visits GET /api/v2/routine/5/structure/ → response cached under key \"routine-api-structure-5\"\n2. Attacker (user B) visits GET /api/v2/routine/5/structure/ → cache hit → returns user A's routine structure without any ownership check\n```\n\nRequires the victim to have previously accessed the endpoint (cache must be populated). Once populated, the cache entry is valid for 1 month.\n\n### Impact\n\nAn attacker with a registered account can retrieve another user's routine details — workout day sequences, exercise structure, training logs, and statistics — from cache without ownership verification.\n\n**Fix**: Include the user ID in the cache key:\n```python\ndef make_routine_api_date_sequence_display_cache_key(routine_id, user_id):\n return f\"routine-api-date-sequence-display-{user_id}-{routine_id}\"\n```\n\nOr move `self.get_object()` before the cache lookup so ownership is always verified first." affected: - package: name: wger ecosystem: PyPI purl: pkg:pypi/wger ranges: - type: ECOSYSTEM events: - introduced: "0" - last_affected: "2.1" versions: - "1.1" - 1.1.1 - "1.2" - 1.2rc1 - "1.3" - "1.4" - "1.5" - "1.6" - 1.6.1 - "1.7" - "1.8" - "1.9" - "2.0" - "2.1" references: - type: WEB url: https://github.com/wger-project/wger/security/advisories/GHSA-42cr-w2gr-m54q - type: ADVISORY url: https://nvd.nist.gov/vuln/detail/CVE-2026-27838 - type: WEB url: https://github.com/wger-project/wger/commit/e964328784e2ee2830a1991d69fadbce86ac9fbf - type: PACKAGE url: https://github.com/wger-project/wger - type: PACKAGE url: https://pypi.org/project/wger - type: ADVISORY url: https://github.com/advisories/GHSA-42cr-w2gr-m54q severity: - type: CVSS_V3 score: CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N