CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27835
4.30.04%

CVE-2026-27835: Do You Even Lift? The wger Workout Leak

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·6 min read·4 visits

PoC Available

Executive Summary (TL;DR)

The wger API forgot to filter database queries by the current user. Authenticated attackers can query specific endpoints to dump the repetition configurations (sets, reps, workout structure) of all users on the instance.

A classic Insecure Direct Object Reference (IDOR) vulnerability in the wger Workout Manager allows authenticated users to access the repetition configurations of every other user on the platform. Due to a failure to filter API querysets by the requesting user, the application serves up the entire database's workout structure to anyone with a valid account.

The Hook: Public Gym, Private Diary?

Let's talk about wger (pronounced however you want, though I lean towards 'wager' that you'll skip leg day). It is the open-source, self-hostable answer to those subscription-heavy fitness apps that hold your data hostage. It manages your workouts, your nutrition, and your progress. It’s a fantastic tool for privacy-conscious gym rats who want to own their data.

But in versions up to 2.4, wger decided that 'community' meant 'radical transparency.' Imagine walking into a gym locker room where every single locker is wide open, and the personal diaries of every member are taped to the doors. That is essentially what happened here.

The vulnerability is a textbook Insecure Direct Object Reference (IDOR), or what the OWASP Top 10 now fancies calling Broken Object Level Authorization (BOLA). While the CVSS score is a modest 4.3 (because apparently, knowing how much your neighbor benches isn't 'Critical' infrastructure damage), the logic flaw represents a fundamental failure in API design. It turns a private workout tracker into a public broadcast system.

The Flaw: The Curse of .all()

Where did the developers go wrong? They fell victim to the path of least resistance in the Django Rest Framework (DRF). DRF is powerful; it automates a lot of the heavy lifting involved in serializing database objects into JSON. But it also gives you enough rope to hang yourself if you aren't paying attention to scoping.

In a proper multi-tenant application (or multi-user, in this case), every single database query regarding user data should have a WHERE clause. You want SELECT * FROM workouts WHERE user_id = current_user. If you forget that WHERE clause, the database happily returns everything.

The flaw in wger was located in the RepetitionsConfigViewSet and MaxRepetitionsConfigViewSet. These views are responsible for serving up the nitty-gritty details of a workout—how many reps, what configuration, etc. Instead of filtering the queryset based on self.request.user, the code simply called .all(). It’s the SQL equivalent of shouting 'EVERYONE!' when asked who is in the room.

The Code: The Smoking Gun

Let’s look at the code. It is almost painful in its simplicity. This is the vulnerable implementation found in wger/manager/api/views.py:

# VULNERABLE CODE
class RepetitionsConfigViewSet(viewsets.ModelViewSet):
    def get_queryset(self):
        # "Here, have everything. I trust you."
        return RepetitionsConfig.objects.all()
 
class MaxRepetitionsConfigViewSet(viewsets.ModelViewSet):
    def get_queryset(self):
        return MaxRepetitionsConfig.objects.all()

See that objects.all()? That is the sound of privacy dying. There is no check to see if the user requesting the data actually owns it. If you have a valid token, you get the list.

Now, let's look at the fix introduced in commit 1fda5690b35706bb137850c8a084ec6a13317b64. The developers switched to a custom base class that likely enforces ownership, and they explicitly filtered the query:

# PATCHED CODE
class RepetitionsConfigViewSet(WgerOwnerObjectModelViewSet):
    def get_queryset(self):
        # "Who are you again? Oh, right. Here is YOUR stuff."
        return RepetitionsConfig.objects.filter(
            slot_entry__slot__day__routine__user=self.request.user
        )

The patch creates a join chain (slot_entry -> slot -> day -> routine -> user) to verify that the config actually belongs to the person asking for it. This is how it should have been from day one.

The Exploit: Skipping Leg Day, Stealing Data

Exploiting this does not require a complex buffer overflow or some wizard-level ROP chain. It requires curl and a registered account. Since wger is often deployed with open registration, the barrier to entry is non-existent.

Step 1: Get in the door. Register an account on the target instance. Log in to get your API token.

Step 2: Ask politely. Send a GET request to the vulnerable endpoint. The API uses sequential IDs (because of course it does), so enumeration is trivial, but you don't even need to iterate IDs here—the list endpoint returns the collection.

# The "Hacker" Tooling
curl -H "Authorization: Token <YOUR_TOKEN>" \
     https://wger-instance.com/api/v2/repetitions-config/

Step 3: Parse the loot. The server responds with a JSON array containing every repetition configuration in the database. You now have the workout structure for every user: specific exercises, rep counts, and routine data. If the IDs are sequential, you can map these configurations back to specific routines and potentially correlate them with specific users if other IDORs exist (which, let's be honest, they probably do).

The Impact: Why Should We Care?

I can hear the detractors now: "So what? They know I do 3 sets of 10. Big deal." And sure, this isn't a dump of credit card numbers or medical records (though health data is protected class in many jurisdictions).

However, consider the context. People use these apps to track progress, physical limitations, and rehabilitation routines. In a competitive environment (say, a sports team using a self-hosted instance), leaking the exact training regimen of your athletes to a rival is a strategic disaster.

Furthermore, this is a privacy violation. Users expect their data to be siloed. If I can see your workout configs, I can infer your activity levels, your schedule, and potentially your location habits if the metadata is rich enough. It is a breach of trust, plain and simple.

The Fix: Authorization is Not Optional

The remediation is straightforward, but it requires diligence. If you are running wger, you need to pull the latest docker image or update your source code immediately. The fix is live in the main branch.

For developers, the lesson is clear: Never trust the client, and never trust the default queryset.

  1. Explicit Filtering: Always override get_queryset in DRF to filter by request.user unless the data is explicitly public.
  2. Test Your Permissions: Write integration tests that attempt to access User A's objects while logged in as User B. If the test passes, your code failed.
  3. Use UUIDs: While not a fix for IDOR, using UUIDs instead of sequential integers makes enumeration significantly more annoying for attackers.

Official Patches

GitHubCommit fixing the permission logic in viewsets

Fix Analysis (1)

Technical Appendix

CVSS Score
4.3/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
EPSS Probability
0.04%

Affected Systems

wger Workout Manager <= 2.4

Affected Versions Detail

Product
Affected Versions
Fixed Version
wger
wger-project
<= 2.4commit 1fda569
AttributeDetail
CWE IDCWE-639
Attack VectorNetwork (API)
CVSS v3.14.3 (Medium)
ImpactInformation Disclosure
Exploit StatusPoC Available
AuthenticationRequired (Low Privilege)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1078Valid Accounts
Defense Evasion
T1083File and Directory Discovery
Discovery
CWE-639
Authorization Bypass Through User-Controlled Key

Known Exploits & Detection

GitHub AdvisoryPoC demonstrating enumeration of repetition configs via curl

Vulnerability Timeline

Vulnerability Disclosed (GHSA)
2026-02-26
Patch Committed
2026-02-26
PoC Published
2026-02-26

References & Sources

  • [1]GHSA-xf68-8hjw-7mpm: Exposure of repetition configuration
  • [2]wger Project Homepage