GHSA-3WGP-X9P5-C7CC

Vulnerability from github – Published: 2026-09-01 18:54 – Updated: 2026-09-01 18:54
VLAI
Summary
Appium: Reflected XSS / arbitrary JS in @appium/base-driver /test/guinea-pig* routes
Details

Summary

Appium's base-driver mounts the built-in /test/guinea-pig, /test/guinea-pig-scrollable and /test/guinea-pig-app-banner routes unconditionally on every server. The handler reflects the throwError query param, the comments POST field, and the User-Agent request header into the returned HTML via compileLodashTemplate, which interpolates <%= expr %> as String(expr) with no HTML/JS escaping. This yields reflected XSS, and the throwError value is reflected inside a <script> block, giving arbitrary JavaScript execution on the server's origin. No authentication, no session, no driver and no plugin are required, and the default bind address is 0.0.0.0.

Details

Affected

  • @appium/base-driver 10.6.0 (with Appium server 3.5.0); tested live.
  • Template engine helper: @appium/base-driver lib/utils.ts compileLodashTemplate.

Location (file:line)

  • Routes mounted unconditionally: base-driver/lib/express/server.ts:216-219 (app.all('/test/guinea-pig', guineaPig) etc.).
  • Tainting: base-driver/lib/express/static.ts:35-61 (guineaPigTemplate) — throwError = String(req.params.throwError ?? req.query?.throwError), params.comment = String(req.body.comments), params.userAgent = req.headers['user-agent'].
  • Unescaped render: base-driver/lib/utils.ts:67-83 (compileLodashTemplate) emits <%= expr %> as String(${expr}) via new Function(...), no escaping.
  • Sinks (shipped templates): base-driver/static/test/guinea-pig.html:11-12 (throwError inside <script>), :50 (comment), :87 (userAgent); same in guinea-pig-scrollable.html / guinea-pig-app-banner.html.

PoC

Requests:

GET /test/guinea-pig?throwError=x%27%2balert(document.domain)%2b%27
POST /test/guinea-pig         (body: comments=</span><img src=x onerror=alert(1)>)
GET  /test/guinea-pig         (header: User-Agent: <script>alert(7)</script>)

image

Impact

An attacker who can get a victim to open a crafted link (or auto-submit a form) to the Appium server executes arbitrary JavaScript on the server's origin. With default CORS * + no authentication, that JS can drive the WebDriver REST API and plugin endpoints. The endpoints are debug/test fixtures that should not be reachable on a production listener at all.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 10.6.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@appium/base-driver"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "10.7.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-58191"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-489",
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-01T18:54:53Z",
    "nvd_published_at": "2026-07-08T21:16:52Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nAppium\u0027s base-driver mounts the built-in `/test/guinea-pig`, `/test/guinea-pig-scrollable` and `/test/guinea-pig-app-banner` routes **unconditionally** on every server. The handler reflects the `throwError` query param, the `comments` POST field, and the `User-Agent` request header into the returned HTML via `compileLodashTemplate`, which interpolates `\u003c%= expr %\u003e` as `String(expr)` with **no HTML/JS escaping**. This yields reflected XSS, and the `throwError` value is reflected **inside a `\u003cscript\u003e` block**, giving arbitrary JavaScript execution on the server\u0027s origin. No authentication, no session, no driver and no plugin are required, and the default bind address is `0.0.0.0`.\n\n## Details\n\n### Affected\n- `@appium/base-driver` **10.6.0** (with Appium server **3.5.0**); tested live.\n- Template engine helper: `@appium/base-driver` `lib/utils.ts` `compileLodashTemplate`.\n\n### Location (file:line)\n- Routes mounted unconditionally: `base-driver/lib/express/server.ts:216-219`\n(`app.all(\u0027/test/guinea-pig\u0027, guineaPig)` etc.).\n- Tainting: `base-driver/lib/express/static.ts:35-61` (`guineaPigTemplate`) \u2014\n`throwError = String(req.params.throwError ?? req.query?.throwError)`, `params.comment = String(req.body.comments)`, `params.userAgent = req.headers[\u0027user-agent\u0027]`.\n- Unescaped render: `base-driver/lib/utils.ts:67-83` (`compileLodashTemplate`)\nemits `\u003c%= expr %\u003e` as `String(${expr})` via `new Function(...)`, no escaping.\n- Sinks (shipped templates): `base-driver/static/test/guinea-pig.html:11-12`\n(`throwError` inside `\u003cscript\u003e`), `:50` (`comment`), `:87` (`userAgent`); same in `guinea-pig-scrollable.html` / `guinea-pig-app-banner.html`.\n\n\n### PoC\n\nRequests:\n```\nGET /test/guinea-pig?throwError=x%27%2balert(document.domain)%2b%27\nPOST /test/guinea-pig         (body: comments=\u003c/span\u003e\u003cimg src=x onerror=alert(1)\u003e)\nGET  /test/guinea-pig         (header: User-Agent: \u003cscript\u003ealert(7)\u003c/script\u003e)\n```\n\n\u003cimg width=\"973\" height=\"276\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f58e1dce-f3ad-43d3-b66e-1ff5efea3866\" /\u003e\n\n\n### Impact\n\nAn attacker who can get a victim to open a crafted link (or auto-submit a form) to the Appium server executes arbitrary JavaScript on the server\u0027s origin. With default CORS `*` + no authentication, that JS can drive the WebDriver REST API and plugin endpoints. The endpoints are debug/test fixtures that should not be reachable on a production listener at all.",
  "id": "GHSA-3wgp-x9p5-c7cc",
  "modified": "2026-09-01T18:54:53Z",
  "published": "2026-09-01T18:54:53Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/appium/appium/security/advisories/GHSA-3wgp-x9p5-c7cc"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-58191"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/appium/pull/22394"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/appium/commit/d94a40af9f8040191ee7888571a1c9d5aec59f89"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/appium/appium"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/appium/releases/tag/@appium/base-driver@10.7.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Appium: Reflected XSS / arbitrary JS in @appium/base-driver /test/guinea-pig* routes"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…