{"id":"GHSA-28f5-38xr-jh2w","summary":"java-client Allows Network Pivot via Unvalidated directConnect Redirect in AppiumCommandExecutor","details":"## Summary\n\nWhen `directConnect(true)` is enabled, appium/java-client unconditionally\naccepts `directConnectHost`, `directConnectPort`, and `directConnectPath`\nfrom the server's NEW_SESSION response and silently redirects all subsequent\nsession traffic to the attacker-specified endpoint — with no allowlist,\nno host validation, and no user notification.\n\n## Affected Code\n\n- `AppiumCommandExecutor.java` (line 196–219): `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 — confirmed via `git diff HEAD` (empty).\n\n## Evidence Screenshots\n\n**Screenshot 1 — 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 — 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)","aliases":["CVE-2026-43910"],"modified":"2026-07-29T03:49:57.245667Z","published":"2026-07-28T14:26:53Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-07-28T14:26:53Z","nvd_published_at":null,"cwe_ids":["CWE-441","CWE-918"]},"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"}],"affected":[{"package":{"name":"io.appium:java-client","ecosystem":"Maven","purl":"pkg:maven/io.appium/java-client"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"8.2.1"},{"fixed":"10.1.1"}]}],"versions":["10.0.0","10.1.0","8.2.1","8.3.0","8.4.0","8.5.0","8.5.1","8.6.0","9.0.0","9.1.0","9.2.0","9.2.1","9.2.2","9.2.3","9.3.0","9.4.0","9.5.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/07/GHSA-28f5-38xr-jh2w/GHSA-28f5-38xr-jh2w.json","last_known_affected_version_range":"\u003c= 10.1.0"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N"}]}