PT-2026-60029 · Pypi · Wger

Published

2026-07-13

·

Updated

2026-07-13

CVSS v3.1

3.1

Low

VectorAV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N

Summary

Five 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.

Details

wger/manager/api/views.py — five actions follow this pattern (lines 134–201):
python
@action(detail=True)
def date sequence display mode(self, request, pk=None):
  cache key = make routine api date sequence display cache key(pk)
  cached = cache.get(cache key)
  if cached:
    return Response(cached)  # returned WITHOUT calling self.get object()
  # only reaches ownership check on cache miss
  routine = self.get object()
  ...
Cache key construction in wger/utils/cache.py:89–106:
python
def make routine api date sequence display cache key(routine id):
  return f"routine-api-date-sequence-display-{routine id}"
  # No user ID in key
Cache TTL: 1 month (4 * 604800 seconds, settings global.py:461).
Affected endpoints:
GET /api/v2/routine/{pk}/date-sequence-display/
GET /api/v2/routine/{pk}/date-sequence-gym/
GET /api/v2/routine/{pk}/structure/
GET /api/v2/routine/{pk}/logs/
GET /api/v2/routine/{pk}/stats/

PoC

1. Victim (user A) visits GET /api/v2/routine/5/structure/ → response cached under key "routine-api-structure-5"
2. Attacker (user B) visits GET /api/v2/routine/5/structure/ → cache hit → returns user A's routine structure without any ownership check
Requires the victim to have previously accessed the endpoint (cache must be populated). Once populated, the cache entry is valid for 1 month.

Impact

An 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.
Fix: Include the user ID in the cache key:
python
def make routine api date sequence display cache key(routine id, user id):
  return f"routine-api-date-sequence-display-{user id}-{routine id}"
Or move self.get object() before the cache lookup so ownership is always verified first.

Fix

Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

PYSEC-2026-3418

Affected Products

Wger