CVE-2026-58500: MCP Appium Fixes XSS in Locator Generator UI

mobile agent free stock image for MCPwatch editorial use
Free stock image for MCPwatch editorial use. Source: Openverse/flickr. Original: Phone security. Creator: Ervins Strauhmanis. License: CC BY 2.0. License URL: https://creativecommons.org/licenses/by/2.0/.

A high-severity cross-site scripting (XSS) flaw in appium-mcp, the official Appium Model Context Protocol server for mobile test automation on Android and iOS, lets attacker-controlled mobile-app element attributes drive script execution through the server’s MCP-UI resource. Tracked as CVE-2026-58500 and fixed in appium-mcp 1.85.10, the issue is a defensive gap, not a remote unauthenticated exploit, but it lands inside a tool an MCP client (Claude Desktop, Cursor, Copilot, and others) invokes on demand.

This is a vulnerability disclosure, not an incident report. The advisory reviewed by MCPwatch does not report exploitation in the wild, and MCPwatch did not reproduce the behavior. Package presence alone does not establish exposure — the issue requires a developer to call generate_locators against an attacker-controlled test app or fixture.

What the advisory establishes

The GitHub Security Advisory GHSA-x975-rgx4-5fh4 and the CVE-2026-58500 record assign a CVSS 3.1 base score of 8.2 (High) to the issue, classified as CWE-79 (Improper Neutralization of Input During Web Page Generation). The affected package is appium-mcp on npm; the advisory lists all versions prior to 1.85.10 as vulnerable. The first patched release is 1.85.10.

The vulnerable component is the createLocatorGeneratorUI function. It builds an HTML template literal that interpolates four categories of mobile-app element attributes — text, content-desc, resource-id, and locator selector values — without HTML or JavaScript context escaping. When the resulting HTML is rendered inside an MCP-UI surface by the connected client, those attributes become attacker-controlled HTML.

Operators should treat the affected versions list as “all releases published before the patch” unless a downstream distribution specifies otherwise. The advisory is the canonical source for the package version boundary and the fix version.

How the attack path is reached

Unlike the SSRF, authorization-bypass, or path-traversal classes MCPwatch has covered across recent MCP CVEs, CVE-2026-58500 does not require network-reachable HTTP endpoints, public clients, or compromised authentication. The published attack chain has three steps:

  1. The attacker controls a mobile application, fixture, or instrumented device that returns attacker-chosen strings in fields such as element text, accessibility content-desc, Android resource-id, or locator selector output.
  2. A developer connects their Appium MCP server to that attacker-supplied app and invokes the generate_locators tool on a target element.
  3. The unescaped strings are interpolated into the MCP-UI HTML returned by createLocatorGeneratorUI. When the connected MCP client renders that resource, the injected markup executes in the client surface.

Inside that client surface, the script context can trigger tool calls, read other UI state, or chain into a second-stage exploit depending on the MCP client’s MCP-UI sandboxing posture. The advisory frames this as “arbitrary tool execution via injected scripts in MCP-UI resource.” MCPwatch treats that second-step reach as client-dependent and does not generalize it beyond the advisory’s framing.

The trust boundary the advisory draws is the mobile-app being tested. A developer who only ever drives generate_locators against first-party apps, internal CI fixtures, or vendor-controlled emulators is not on the attack path. The exposure grows when developers use community-shared apps, third-party test fixtures, customer-supplied builds, or remote-device farms as targets for the locator generator.

What changed in 1.85.10

The patch in 1.85.10 rewrites createLocatorGeneratorUI to escape each of the four attribute categories before they enter the HTML template, so injected markup is rendered as text rather than parsed as DOM. The function signature and the public MCP-UI surface are preserved; the change is internal to the generator’s HTML composition. Operators on 1.85.9 or earlier should treat the upgrade as a regular dependency update, not a breaking change.

The advisory does not list any compensating control that fully replaces the patch. Possible mitigations for deployments that cannot upgrade immediately include restricting the generate_locators tool to first-party apps, disabling the MCP-UI rendering of createLocatorGeneratorUI output in the client, and isolating the MCP server from untrusted test apps — each of these reduces the exposure surface but does not eliminate the underlying interpolation defect.

Operator checks

  1. Inventory any deployment of appium-mcp in your environment (developer workstations, CI runners, internal device farms): npm ls appium-mcp or check package.json / package-lock.json for the resolved version.
  2. If versions below 1.85.10 are present, upgrade to 1.85.10 or later as a regular dependency update. Review changelog entries between your pinned version and 1.85.10 for any other behavioral changes; the locator-generator XSS fix is the security-relevant delta.
  3. Audit which mobile apps, fixtures, and remote devices are reachable from MCP clients that have generate_locators exposed. Treat third-party apps, customer-supplied builds, and unverified cloud-device endpoints as untrusted input sources for the tool until those apps are reviewed.
  4. For MCP clients that allow disabling or sandboxing MCP-UI rendering of locator-generator output, enable that posture on developer workstations used for untrusted test targets.
  5. Re-run the locator generator against a known fixture after upgrading and confirm the rendered UI still produces the expected selectors. The patch is HTML-composition only and should not change valid locator output.

Context for MCPwatch readers

CVE-2026-58500 is the second MCP server-side input-handling issue MCPwatch has tracked this quarter where the attack path runs through a tool the developer actively invokes — the first was the ToolHive host-side SSRF path MCPwatch covered on CVE-2026-58196. The trust model is the same in both cases: an MCP tool’s inputs come from somewhere the developer did not personally author, and the server’s job is to refuse to treat those inputs as code.

This also fits the broader MCP-specific pattern that OWASP’s MCP Top 10 entry on tool poisoning is documenting — tool descriptions, return values, and side outputs that an LLM client treats as instructions without first validating context. The NSA’s May 2026 CSI on MCP security reads the same trust-boundary question from a government perspective. Both expect MCP servers to escape, normalize, or sandbox tool output before it reaches a rendering surface, regardless of whether the client is a model, a developer IDE, or an MCP-UI view.

MCPwatch’s assessment: this is a single-component vulnerability with a clean upgrade path and no reported exploitation. The defensive lesson is to keep MCP server output escaping uniform across all surfaces — tool result JSON, log lines, error messages, and UI templates — and to treat mobile test fixtures with the same input-validation posture as production web form data.

Sources

Leave a Comment