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)
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
- 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
- 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.
- 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.
- 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_sessionswitches 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.
- Callback handler with no request-origin check: src/core/jsonrpc.rs#L463-L568
- Token exchange and session store inside the handler: src/core/jsonrpc.rs#L519 and #L551
- Route registration: src/core/jsonrpc.rs#L603
/auth/telegramon the list of paths that skip the bearer check: src/core/auth.rs#L51-L64store_sessionactivates the user-scoped directory with no in-app confirmation: src/openhuman/credentials/ops.rs#L154-L185- Default port 7788: src/core/jsonrpc.rs#L892-L897
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-Modemust benavigateandSec-Fetch-Destmust bedocument, which rules out images, frames, scripts andfetch(). A cross-site request must come fromhttps://t.me/orhttps://web.telegram.org/. WithoutSec-Fetch-Site, theReferermust 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/telegramand the desktop/authfallback 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
- Reported privately via GitHub PVR (GHSA-c4m9-hw7m-vv3m), with a suggested fix and a patch branch ready.
- Maintainers merge #2331, which includes the fetch-metadata gate (ab37f6c).
- Maintainer requests a CVE through GitHub.
- OpenHuman 0.56.0 released with the fix.
- #6318 removes the public login callbacks from the core.
- We ask the maintainer to publish the advisory.
- OpenHuman 0.64.0 released without
/auth/telegram. - Maintainer publishes GHSA-c4m9-hw7m-vv3m with CVE-2026-49410; public write-up.
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon.
References
- Fix PR (merged 2026-05-21): tinyhumansai/openhuman#2331; fix commit ab37f6c
- Fixed release: OpenHuman 0.56.0
- Route removed: tinyhumansai/openhuman#6318, released in OpenHuman 0.64.0
- GitHub advisory: GHSA-c4m9-hw7m-vv3m
- CVE: CVE-2026-49410 (assigned by the GitHub CNA; the record was not yet public in the CVE List on 2026-10-09)
- Affected repository: tinyhumansai/openhuman