PHP2Shell: Read our blog on the critical RCE vulnerabilities affecting 70% of the Internet

CVE-2026-46438: 
Python vulnerability analysis and mitigation

Overview

CVE-2026-46438 is a cross-user data corruption vulnerability in wger, a free open-source workout and fitness manager, caused by a missing ownership check on the WorkoutLog.slot_entry foreign key. An authenticated attacker can inject arbitrary workout log entries into any other user's SlotEntry by supplying the victim's slot_entry ID in a POST /api/v2/workoutlog/ request, silently corrupting the victim's progressive-overload calculations. The vulnerability affects wger versions prior to 2.6 and was published on October 7, 2026. It carries a CVSS v3.1 base score of 6.5 (Medium) (Github Advisory, wger Security Advisory).

Technical details

The root cause is a logic flaw classified as CWE-639 (Authorization Bypass Through User-Controlled Key) and CWE-862 (Missing Authorization). wger's centralized ownership-verification mechanism in WgerOwnerObjectModelViewSet.create() (file: wger/utils/viewsets.py) only checks foreign keys explicitly listed by each ViewSet's get_owner_objects() method. WorkoutLogViewSet.get_owner_objects() returns only (Routine, 'routine') and (WorkoutSession, 'session'), omitting (SlotEntry, 'slot_entry') entirely — meaning an attacker can supply their own routine ID (which passes the check) alongside a victim's slot_entry ID (which is never verified). A second contributing flaw in SlotEntry.get_config_data() retrieves associated logs via self.workoutlog_set.all() with no user filter, so injected entries from any user are included in the victim's progression calculations (wger Security Advisory).

Impact

Successful exploitation allows any authenticated user to silently corrupt another user's fitness training data by injecting fake workout log entries (e.g., weight=999, repetitions=999) that are folded into the victim's auto-generated progressive-overload targets. The victim receives no notification, and the injected data does not appear in their own log view, making the corruption difficult to detect. The attack is scalable — an attacker can iterate over sequential slot_entry IDs to corrupt training data across all users on a shared wger instance. There is no confidentiality or availability impact; the impact is limited to high integrity loss of user fitness data (wger Security Advisory, Github Advisory).

Exploitability

A complete, runnable Python PoC script is publicly available in the wger security advisory, demonstrating the full attack flow against a live wger instance (wger Security Advisory). The exploit requires authentication (low privileges) but no user interaction, and the attack complexity is low. The EPSS score is approximately 0.227% (12th percentile), indicating a low but non-negligible probability of exploitation in the wild. There is no evidence of in-the-wild exploitation at this time, and the vulnerability is not listed in the CISA KEV catalog. Feedly classifies the exploit confidence as high based on the completeness of the PoC (Github Advisory).

Exploitation steps

  1. Authenticate as attacker: Obtain an authentication token by sending credentials to POST /api/v2/login/ (or register a new account via POST /api/v2/register/ if open registration is enabled).
  2. Enumerate victim's SlotEntry ID: Discover the victim's SlotEntry ID through sequential ID enumeration (IDs are integers) via API requests, or by leveraging any information disclosure in the application.
  3. Create an attacker-owned Routine: Send POST /api/v2/routine/ with the attacker's token to create a routine. This routine ID will pass the ownership check in WorkoutLogViewSet.get_owner_objects().
  4. Inject fake WorkoutLog entry: Send the following request using the attacker's token:
POST /api/v2/workoutlog/
Authorization: Token <attacker_token>
Content-Type: application/json

{
  "routine": <attacker_routine_id>,
  "slot_entry": <victim_slot_entry_id>,
  "exercise": <any_exercise_id>,
  "repetitions": 999,
  "weight": 999,
  "repetitions_unit": 1,
  "weight_unit": 1,
  "date": "2025-01-15",
  "iteration": 1
}
  1. Confirm injection: The server returns HTTP 201 with the created WorkoutLog record referencing the victim's slot_entry ID, confirming the cross-user reference was accepted.
  2. Verify data corruption: Optionally authenticate as the victim and call GET /api/v2/routine/{victim_routine_id}/date-sequence-display/ to confirm the injected fake values (weight=999, reps=999) are now included in the victim's progressive-overload calculations (wger Security Advisory).

Indicators of compromise

  • Network: Unusual POST /api/v2/workoutlog/ requests where the routine ID belongs to one user but the slot_entry ID belongs to a different user; high-frequency sequential API requests to /api/v2/workoutlog/ from a single authenticated account suggesting automated ID enumeration.
  • Logs: API access logs showing HTTP 201 responses to POST /api/v2/workoutlog/ with cross-user foreign key combinations; repeated requests to /api/v2/slot-entry/ or /api/v2/routine/ endpoints from a single account in rapid succession.
  • Application Data: Workout log entries in the database where the routine owner differs from the slot_entry owner; anomalous weight or repetitions values (e.g., 999) appearing in users' progression data that do not match their own logged sessions (wger Security Advisory).

Mitigation and workarounds

Upgrade to wger version 2.6 or later, which contains the patch for this vulnerability (wger Release 2.6). The primary fix adds (SlotEntry, 'slot_entry') to the list returned by WorkoutLogViewSet.get_owner_objects() in wger/manager/api/views.py, ensuring the slot_entry foreign key is subject to ownership verification. A defense-in-depth fix also filters logs by the routine owner in SlotEntry.get_config_data() using self.workoutlog_set.filter(user=self.slot.day.routine.user). No configuration-based workaround is available for unpatched versions; upgrading is the only remediation (wger Security Advisory).

Community reactions

The vulnerability was reported by security researcher KadirArslan and published by wger project maintainer rolandgeider on October 4, 2026, with the GitHub Advisory Database entry updated on October 7, 2026 (Github Advisory). No significant broader media coverage or notable community commentary beyond the official advisory has been identified at this time.

Additional resources


Source: This report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-c978-59m8-c77vHIGH7.8
  • Python logoPython
  • virtualenv
NoYesOct 21, 2026
GHSA-cw65-gx24-rc82MEDIUM4.5
  • Python logoPython
  • virtualenv
NoYesOct 21, 2026
CVE-2026-113716MEDIUM4.5
  • Python logoPython
  • virtualenv
NoYesOct 21, 2026
GHSA-43mp-35q3-x3fqMEDIUM4.5
  • Python logoPython
  • virtualenv
NoYesOct 21, 2026
CVE-2026-113724MEDIUM4.5
  • Python logoPython
  • virtualenv
NoYesOct 21, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management