GHSA-28F5-38XR-JH2W

Vulnerability from github – Published: 2026-07-28 14:26 – Updated: 2026-07-28 14:26
VLAI
Summary
java-client Allows Network Pivot via Unvalidated directConnect Redirect in AppiumCommandExecutor
Details

Summary

When directConnect(true) is enabled, appium/java-client unconditionally accepts directConnectHost, directConnectPort, and directConnectPath from the server's NEW_SESSION response and silently redirects all subsequent session traffic to the attacker-specified endpoint — with no allowlist, no host validation, and no user notification.

Affected Code

  • AppiumCommandExecutor.java (line 196–219): setDirectConnect() builds a new URL from server-supplied fields and calls overrideServerUrl(newUrl) without validating host/IP.
  • DirectConnect.java: getUrl() constructs protocol://host:port/path with no allowlist.

Root Cause

Only the protocol is validated (must equal "https"). The destination host and port are never checked against any allowlist or denylist.

PoC (confirmed)

A rogue server injecting directConnectHost=127.0.0.1:4443 causes the client to silently redirect all post-session commands:

[bootstrap] POST /wd/hub/session [bootstrap] Injecting directConnect -> https://127.0.0.1:4443/wd/hub [redirect-target] HIT #1: GET /wd/hub/session/poc-session-001/source [redirect-target] HIT #2: DELETE /wd/hub/session/poc-session-001

Original source code unmodified — confirmed via git diff HEAD (empty).

Evidence Screenshots

Screenshot 1 — Rogue server capturing redirected traffic:

1

Screenshot 2 — Java client processing response from attacker host:

2

Impact

  • Full interception of session traffic
  • Network pivot to internal hosts (RFC-1918, 169.254.169.254)
  • Cloud credential theft via IMDS endpoint
  • Escalates to ~8.1 High in CI/CD environments where directConnect(true) is set in shared base configuration

Suggested Fix

Add allowlist validation before overrideServerUrl() is called, and/or block RFC-1918/loopback/link-local destinations by default.

poc_appium_directconnect.zip

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 10.1.0"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.appium:java-client"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.2.1"
            },
            {
              "fixed": "10.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-43910"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-441",
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-28T14:26:53Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\n\nWhen `directConnect(true)` is enabled, appium/java-client unconditionally\naccepts `directConnectHost`, `directConnectPort`, and `directConnectPath`\nfrom the server\u0027s NEW_SESSION response and silently redirects all subsequent\nsession traffic to the attacker-specified endpoint \u2014 with no allowlist,\nno host validation, and no user notification.\n\n## Affected Code\n\n- `AppiumCommandExecutor.java` (line 196\u2013219): `setDirectConnect()` builds\n  a new URL from server-supplied fields and calls `overrideServerUrl(newUrl)`\n  without validating host/IP.\n- `DirectConnect.java`: `getUrl()` constructs `protocol://host:port/path`\n  with no allowlist.\n\n## Root Cause\n\nOnly the protocol is validated (must equal \"https\"). The destination host\nand port are never checked against any allowlist or denylist.\n\n## PoC (confirmed)\n\nA rogue server injecting `directConnectHost=127.0.0.1:4443` causes the\nclient to silently redirect all post-session commands:\n\n[bootstrap]       POST /wd/hub/session\n[bootstrap]       Injecting directConnect -\u003e https://127.0.0.1:4443/wd/hub\n[redirect-target] HIT #1: GET /wd/hub/session/poc-session-001/source\n[redirect-target] HIT #2: DELETE /wd/hub/session/poc-session-001\n\nOriginal source code unmodified \u2014 confirmed via `git diff HEAD` (empty).\n\n## Evidence Screenshots\n\n**Screenshot 1 \u2014 Rogue server capturing redirected traffic:**\n\n\u003cimg width=\"887\" height=\"146\" alt=\"1\" src=\"https://github.com/user-attachments/assets/cc28002c-ea20-4ac8-8336-cec632e3c842\" /\u003e\n\n**Screenshot 2 \u2014 Java client processing response from attacker host:**\n\n\u003cimg width=\"788\" height=\"130\" alt=\"2\" src=\"https://github.com/user-attachments/assets/222cbab0-0d53-45b2-847d-6aa4e3b79370\" /\u003e\n\n## Impact\n\n- Full interception of session traffic\n- Network pivot to internal hosts (RFC-1918, 169.254.169.254)\n- Cloud credential theft via IMDS endpoint\n- Escalates to ~8.1 High in CI/CD environments where directConnect(true)\n  is set in shared base configuration\n\n## Suggested Fix\n\nAdd allowlist validation before `overrideServerUrl()` is called, and/or\nblock RFC-1918/loopback/link-local destinations by default.\n\n[poc_appium_directconnect.zip](https://github.com/user-attachments/files/26472525/poc_appium_directconnect.zip)",
  "id": "GHSA-28f5-38xr-jh2w",
  "modified": "2026-07-28T14:26:53Z",
  "published": "2026-07-28T14:26:53Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/appium/java-client/security/advisories/GHSA-28f5-38xr-jh2w"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/java-client/pull/2408"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/java-client/commit/2b9cd442b9dbf56ccc6f1e83aeeb411c0ec230c9"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/appium/java-client"
    },
    {
      "type": "WEB",
      "url": "https://github.com/appium/java-client/releases/tag/v10.1.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "java-client Allows Network Pivot via Unvalidated directConnect Redirect in AppiumCommandExecutor"
}



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…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…