OpenEMR: a callback returned a service login token

CVE-2026-24898 · CVSS 10.0

OpenEMR is open-source software for medical records. It connects to MedEx, an outside service that handles appointment reminders. OpenEMR stores the practice's MedEx login, so it can log in to MedEx by itself.

MedEx also sends messages back to OpenEMR through a callback. A callback is a URL on your server that another service calls to deliver a message. The caller is a service and not a person, so a callback cannot use the normal login form. It needs another check, one that proves the caller is really that service.

Illustrative pseudocode, simplified from MedEx.php and API.php before the fix.
# MedEx.php: the callback URL
ignore_auth = true    # No user login.
load_openemr()

if post["callback_key"] is not empty:
    medex = MedEx("MedExBank.com")
    status = medex.login(force=2)
    respond_json(status)
    exit

respond_text("Not logged in")

# API.php
MedEx.login(force):
    info = read_preferences()
    if info is incomplete or disabled:
        return false
    info.callback_key = post["callback_key"]
    # Uses the stored username and API key.
    info = just_login(info)
    return info.status

In the pseudocode, the top part is the callback URL. Setting ignore_auth turns off the normal login, which is reasonable for a callback. The if is the only check that remains. It asks if the request has a field called callback_key, and any value that is not empty passes.

The field has the name of a secret, but OpenEMR does not compare it with a secret. It only forwards the value to MedEx, as part of its own login. So the check says something about the shape of the message and nothing about its sender. Any program that can reach the URL looks the same as MedEx.

MedEx.login then uses the practice's own access. It reads the stored username and API key, and it logs in to MedEx with them. The callback URL sends the result to the caller. The advisory says that this result holds a bearer token, a secret string that works in place of a password for whoever holds it. It also holds details of the practice and its reminder events, and these can identify patients.

So the caller never needed the practice's password. OpenEMR already had the right to log in, and an unchecked message made it use that right and hand over the result. The flaw needs the MedEx integration to be turned on. The advisory demonstrates this exposure, and it describes later use of the token as a possible next step.

AISLE reports AI-assisted discovery. OpenEMR credits its researchers and lists version 8.0.0 as fixed.