Threat Research Meets AI: How We Found 13 UXSS Vulnerabilities in Android WebView

We found the first 7 UXSS vulnerabilities through manual reverse engineering. Then, we formalized the patterns and pointed Novee at 20 Android apps. It found five more, plus a critical account takeover.

Omri Inbar, Security Engineer
Elad Meged, Founding Engineer & Security Researcher, Discovered hundreds of Zero-Days

8 mins

continuous ai pentesting
Explore Article +

Introduction 

This post describes security research conducted under responsible disclosure. Don’t test systems you don’t own or have explicit permission to assess. Full details on this research are forthcoming.

This research examines one vulnerability class, Universal Cross-Site Scripting (UXSS) in Android WebView. It details how we took an  instance found manually, synthesized it into a pattern Novee hunts for automatically, and set it loose on twenty different Android apps to find critical bugs.

Those 20 Android apps span browsers, OEM preinstalled apps, messaging platforms, and e-commerce apps. Not only did we find the UXSS pattern in 12 of them, but we also discovered a critical account takeover that needed no UXSS at all. Billions of installations potentially affected, all responsibly disclosed.

What Is UXSS, and Why Should You Care?

Regular XSS lets an attacker run JavaScript on one vulnerable website. Universal XSS is a bigger problem entirely.

With UXSS, an attacker can execute JavaScript on any origin they choose: your bank, your email, your company’s internal apps. The flaw sits in the software doing the rendering rather than in the site being targeted. A victim opens an attacker-controlled page or taps a single link, and the attacker gets full script execution on whatever sensitive site they’ve picked.

On Android, WebView is the backbone of in-app browsers, embedded web content, and hybrid apps, so a UXSS bug there is serious. It can mean session hijacking on any site, sometimes reaching cookies that were supposed to be off-limits, full account takeover of services rendered inside WebView, a complete bypass of the site’s content security policy because the injection comes from the native layer underneath it, and convincing phishing on trusted domains, occasionally with almost no interaction from the victim at all.

The Manual Research: Finding the First Seven Bugs

We started where this kind of research usually starts, with hands on the code, reversing Android apps to understand how their WebView bridges actually behave.

It helps to picture the JavaScript bridge as a two-lane road. 

The inbound road (web calling native), has been studied to death. Developers add origin checks, token validation, and domain whitelists; OWASP documents it; static analysis tools flag it. 

The outbound road (native replying to web) has been almost entirely ignored.

The Pattern in Plain Terms

We manually discovered a Time-of-Check, Time-of-Use (TOCTOU) race on origin:

  1. Check: The attacker’s page passes all inbound validation (whitelists, bridge authentication, origin checks)
  2. Gap: The app performs asynchronous work: an IO operation, a dialog display, a hardware event listener
  3. Navigate: During the async gap, the attacker navigates the WebView to a victim origin
  4. Use: The native callback fires and blindly calls evaluateJavascript() on whatever page is now loaded – the victim’s page

This isn’t a timing race you need to win in microseconds. Many of these async gaps are user-triggered: a dialog dismissal, a volume button press, an app switch. The attacker has all the time in the world.

Seven bugs. Two distinct families. Now we had formalized patterns we could teach Novee.

Teaching the Pattern to Novee

We encoded the reasoning itself: find the outbound paths where native code replies to web content, work out whether those paths check the current origin at the moment they execute, and spot the async gaps an attacker could use to swap the page between the call and the reply. Novee reasons about the pattern semantically, which is why it held up across codebases that looked nothing alike.

Both of the two families we found come down to a reply landing on the wrong page.

In the first, bridge reply-path UXSS, native code holds onto a callback while it does asynchronous work, and by the time it fires the reply, the attacker has swapped the WebView to a victim site, so the script runs there instead.

The second family, navigation-path UXSS, abuses how apps handle intents, deep links, and fallback URLs to smuggle a javascript: link onto a page that’s already open, which sails underneath the site’s content security policy.

Different mechanics, same root cause: the code trusts the origin it checked earlier rather than the one actually loaded when it acts.

Beyond UXSS: An Account Takeover From One Bad Pattern Match

Novee also uncovered a critical account takeover in a major e-commerce app that involved no UXSS at all. The app decided whether to trust a calling page by matching its address against a pattern, and that pattern was written loosely enough that an attacker could host a page at an address that merely contained the trusted domain somewhere inside it. That page passed the check and gained full access to the app’s authenticated bridge, including a method that handed back the user’s access token, email, and account identifiers.

The whole thing ran from a single tap on a link, silently, with the victim none the wiser. One tap, full account takeover, all from a single sloppy pattern match.

The Impact

Prior WebView research has overwhelmingly focused on the inbound path: who can call native bridges and whether origin checks exist on @JavascriptInterface methods. Our manual work showed that even apps with perfect inbound security can carry trivially exploitable UXSS through their outbound reply path, and Novee now checks this systematically on every mobile app it tests.

We didn’t stop at one bug and a rule to match it. We taught Novee to reason about the TOCTOU-on-origin pattern semantically, understanding async gaps, callback storage, and origin validation at a conceptual level. 

The pattern fits in a single sentence, “does the callback check the origin before executing?”, yet Novee applied it across wildly different codebases and turned up a dozen distinct vulnerabilities, many triggered by ambient user actions rather than microsecond races, and every one of them bypassing Content Security Policy completely. The cross-app composition finding goes a step further, breaking the assumption that an app’s security can be evaluated in isolation.

Recommended Defenses

For application developers using WebView:

  1. Treat every evaluateJavascript() and loadUrl(“javascript:…”) as a potential UXSS sink. Audit every call site and trace backwards to the trigger.
  2. Bind callbacks to the originating document. Invalidate stored callbacks when the page navigates, using onPageStarted() or navigation callbacks to clear pending state.
  3. Re-validate origin at use time, not just at call time. The page may have changed between call and reply.
  4. Validate browser_fallback_url schemes. Allow only http:// and https://, and never pass unvalidated URLs to loadUrl().
  5. Never declare javascript: as a browsable scheme in your AndroidManifest.
  6. Migrate to WebViewCompat.addWebMessageListener() (API 33+), which drops replies when the originating frame navigates away and is immune to this pattern by design.
  7. Test cross-app composition. Your attack surface changes based on what else is installed, so test with apps that declare unusual intent filters.

If you maintain an Android application that uses WebView bridges or processes javascript: URIs from intents, audit your outbound reply paths. The inbound road has guardrails. The outbound road, in most apps we tested, has none. 

Novee is One AI Pentesting Platform for the Whole Attack Surface

The mobile testing that produced these findings is live in the Novee platform. Every customer gets the patterns Novee learned here.

Most breaches don’t respect the boundaries security teams draw on their architecture diagrams. An attacker who can’t get through the web front end will pivot to the mobile app, and one who can’t break the mobile app will go straight at the API sitting behind both. Novee tests all of it from a single platform: the backend APIs, the web applications, and the mobile apps, with every finding tracked in one dashboard. 

How it works. Novee brings the AI-powered platform we already run for web over to mobile: users upload an APK, and the agent handles the rest, pairing static analysis of the package with live runtime testing in one assessment. It maps the full Android attack surface, activities, services, deep links, content providers, intents, WebViews, and broadcast receivers, with every assessment mapped to OWASP MASTG and MASVS coverage across storage, crypto, authentication, network, platform, code, and resilience. Every finding comes proven, with exploit evidence and replication steps, and each fix is tailored to the stack and retested automatically to confirm the risk is closed.

The Asset Intelligence Model (AIM) builds a living picture of each mobile app, its workflows, permissions, APIs, and business logic, so testing sharpens each cycle rather than resetting to zero. Because mobile and web share one platform, you get unified risk tracking alongside MASTG-mapped evidence that holds up for SOC 2, ISO 27001, and customer due diligence.

Let us show you what your attackers already see. Explore the Novee platform.

Stay updated

Get the latest insights on AI, cybersecurity, and continuous pentesting delivered to your inbox