Security

OpenHuman: CSRF on /auth/telegram implants the attacker's session

OpenHuman local core - CSRF on /auth/telegram allows session implantation by any web page (GHSA-c4m9-hw7m-vv3m)

PUBLISHED SEVERITY HIGHSTATUS PatchedGHSA-c4m9-hw7m-vv3m
Patched

Fixed in OpenHuman 0.56.0 (2026-05-27) by #2331, which puts a fetch-metadata and Referer gate in front of /auth/telegram. 0.64.0 (2026-09-25) removes the route. Track the fix at tinyhumansai/openhuman#2331.

Product
OpenHuman (desktop app core) in tinyhumansai/openhuman
Affected versions
OpenHuman before 0.56.0. Fixed in 0.56.0 (2026-05-27). From 0.64.0 (2026-09-25) the local core no longer serves a public login callback at all.
Severity
HIGH
Status
Patched
Weaknesses
  • CWE-352Cross-Site Request Forgery (CSRF)
  • CWE-384Session Fixation
As filed on the advisory.
GitHub advisory
GHSA-c4m9-hw7m-vv3m
Published by the maintainer on 2026-10-09
CVE
CVE-2026-49410
Published
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon (https://www.aeon.fun).

What users should do now

  1. Update OpenHuman to the latest release. 0.56.0 is the first fixed release; 0.64.0 and later no longer expose a public login callback on the local core.
  2. If you ran an older version, check which account the app is signed in to. If it is not yours, sign out, sign back in with your own account, and review recent agent activity and memory for anything you did not expect to share.
  3. Until you update, only open login links that the OpenHuman Telegram bot sent you, and quit the app when you are not using it.

Summary

The OpenHuman desktop app runs a local core HTTP server on 127.0.0.1:7788. Its GET /auth/telegram?token=... route is the landing page for the login link the Telegram bot sends. It had no bearer check (it was on the public path list) and no check that the request came from a real click on that link. It traded the one-time token with the backend for a session JWT and stored that JWT as the app's active local session. Any web page open in the user's browser could make the browser load that URL with a token the attacker had created for their own account, and the user's app would switch to the attacker's account.

Affected versions

OpenHuman before 0.56.0, while the desktop app (and so the local core on port 7788, the default) is running. The core binds to loopback by default, so the attacker reaches it through the user's browser, not over the network.

Impact

  • Session implantation. After one drive-by page visit, the user's local app is signed in to the attacker's backend account. Later agent actions, memory writes and Telegram messages the user sends through the app are tied to the attacker's account on the cloud side, where the attacker can watch them by signing in to the same account.
  • Local data re-rooted. store_session switches the active user (active_user.toml) and the user-scoped data directory to the attacker's user id, so new local data is filed under the attacker's account.
  • Low bar. The attacker needs only their own account on the same bot and a way to get a page in front of the user (a link, an ad, an embedded frame). The port is fixed by default, so no scanning is needed. The side effect happens on a plain GET, so CORS does not stop it.

Scored 8.1 (CVSS 3.1 AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N) on the advisory.

Affected code

Permalinks at beba562, the last commit on main before the fix.

Fix

  • ab37f6c ("gate telegram callback on fetch-metadata + referer"), part of #2331, checks the request before the token is used. When the browser sends fetch-metadata headers, Sec-Fetch-Mode must be navigate and Sec-Fetch-Dest must be document, which rules out images, frames, scripts and fetch(). A cross-site request must come from https://t.me/ or https://web.telegram.org/. Without Sec-Fetch-Site, the Referer must be Telegram or loopback. Anything else gets HTTP 403. Released in 0.56.0.
  • #6318 (merged 2026-09-16) moves login out of the core: the core now takes a credential from the host app, and /auth/telegram and the desktop /auth fallback are removed from the core router and from the public path list. Released in 0.64.0.

Detection (for defenders)

Look in the core log for [auth:telegram] Received registration callback with token or Session stored successfully lines at times the user did not click a bot login link. On disk, an active_user.toml or a users/<uid>/ directory for a user id that is not the user's own is a strong sign. In the app, check that the signed-in account is the expected one. A working exploit is withheld.

Timeline

  1. Reported privately via GitHub PVR (GHSA-c4m9-hw7m-vv3m), with a suggested fix and a patch branch ready.
  2. Maintainers merge #2331, which includes the fetch-metadata gate (ab37f6c).
  3. Maintainer requests a CVE through GitHub.
  4. OpenHuman 0.56.0 released with the fix.
  5. #6318 removes the public login callbacks from the core.
  6. We ask the maintainer to publish the advisory.
  7. OpenHuman 0.64.0 released without /auth/telegram.
  8. Maintainer publishes GHSA-c4m9-hw7m-vv3m with CVE-2026-49410; public write-up.

Credit

Finder: Aaron Elijah Mars of Aeon. Tool: Aeon.

References