Skip to content

[PM-34487] llm: Add Android device interaction MCP server with ADB tooling#6747

Open
SaintPatrck wants to merge 10 commits intomainfrom
chore/improve-android-ui-verification-skill
Open

[PM-34487] llm: Add Android device interaction MCP server with ADB tooling#6747
SaintPatrck wants to merge 10 commits intomainfrom
chore/improve-android-ui-verification-skill

Conversation

@SaintPatrck
Copy link
Copy Markdown
Contributor

@SaintPatrck SaintPatrck commented Mar 31, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-34487

📔 Objective

Add a TypeScript MCP server and companion skill for structured Android device interaction via ADB. Replaces the initial shell script approach with proper XML parsing, structured dumpsys window parsing, and native geometry for obstruction detection.

🏗️ Architecture

Claude Code ──stdio──> MCP Server (TypeScript)
                         ├── tools/        (6 tool handlers)
                         ├── adb/          (execFile wrapper, device discovery)
                         ├── parsers/      (UIAutomator XML, dumpsys window)
                         └── geometry/     (bounds, obstruction, visible-region)

🔧 MCP Tools

Tool Description
capture Dump UI hierarchy XML and/or screenshot
find_element Find element by text/content-desc with two-layer obstruction detection
tap_element Find + tap + capture (auto-adjusts for obstructions)
tap_at Tap specific coordinates + capture
navigate Home, back, app-drawer navigation + capture
input_text Type text into focused field with shell-safe escaping

🛡️ Obstruction Detection

Two-layer system for detecting when UI elements are blocked:

  • Layer 1 — System overlays: Parses dumpsys window windows for TalkBack, PiP, accessibility overlays using touchable region bounds
  • Layer 2 — In-app elements: Finds topmost clickable element at tap point via XML tree traversal (catches FABs, dialogs, bottom sheets)

When obstructed, computes the largest visible strip (top/bottom/left/right of obstructor) and returns adjusted tap coordinates.

📁 Key Files

  • .mcp.json — MCP server config (stdio, auto-build)
  • .claude/mcp/android-device-server/ — TypeScript MCP server (self-contained for future plugin extraction)
  • .claude/skills/interacting-with-android-device/SKILL.md — Companion skill with tool docs and allowed-tools

✅ Testing

  • 57 unit tests across geometry, parsers, ADB discovery (fixture-based, no device required)
  • fast-xml-parser for UIAutomator XML → typed tree
  • Zod validation on all tool inputs
  • execFile (not exec) prevents host-side command injection

@SaintPatrck SaintPatrck added the ai-review-vnext Request a Claude code review using the vNext workflow label Mar 31, 2026
@github-actions github-actions bot added the t:llm Change Type - LLM related change (e.g. CLAUDE.md files) label Mar 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed 26 new files (2661 additions) adding a TypeScript MCP server for Android device interaction via ADB. The server provides 6 tools (capture, find_element, tap_element, tap_at, navigate, input_text) with structured XML parsing, dumpsys window parsing, and two-layer obstruction detection. Security posture is sound: execFile prevents host-side command injection, Zod validates all tool inputs, and shell escaping covers the special characters for double-quoted strings. Architecture is clean with proper separation between ADB wrapper, parsers, geometry, and tool handlers. Test coverage is thorough with 57 unit tests including real dumpsys fixture data and geometry edge cases.

Code Review Details

No findings met the confidence threshold for inline comments. Potential concerns evaluated and dismissed:

  • Shell injection via adb.shell(): All callers pass hardcoded strings or Zod-validated numbers; execFile prevents host-side injection
  • StatusBar/NavigationBar false positives in overlay detection: Correct behavior since ADB taps dispatch through the window manager to the topmost touchable window
  • input text %s to space conversion: Android platform behavior in the input command, not addressable at the shell escaping layer
  • readFileSync in find-element pipeline: Acceptable for single-request MCP server model
  • drawingOrder parsed but unused: Minor unused field, not actionable

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.58%. Comparing base (5d7ea8f) to head (7f3e6d5).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6747      +/-   ##
==========================================
+ Coverage   84.75%   85.58%   +0.83%     
==========================================
  Files         944      820     -124     
  Lines       60715    58162    -2553     
  Branches     8569     8504      -65     
==========================================
- Hits        51456    49776    -1680     
+ Misses       6293     5436     -857     
+ Partials     2966     2950      -16     
Flag Coverage Δ
app-data 17.64% <ø> (+0.22%) ⬆️
app-ui-auth-tools 20.54% <ø> (+0.22%) ⬆️
app-ui-platform 15.39% <ø> (-0.61%) ⬇️
app-ui-vault 25.70% <ø> (-1.07%) ⬇️
authenticator 6.53% <ø> (+0.01%) ⬆️
lib-core-network-bridge 4.24% <ø> (+0.01%) ⬆️
lib-data-ui 0.94% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…ripts

Provides Claude with structured guidance for Android device interaction
via ADB — capturing UI state, tapping elements, navigating, and
verifying screens — with scoped allowed-tools and helper scripts that
reduce token overhead on repetitive operations.
@SaintPatrck SaintPatrck force-pushed the chore/improve-android-ui-verification-skill branch from d527819 to 483c8e7 Compare March 31, 2026 17:26
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

Logo
Checkmarx One – Scan Summary & Details2be4c72c-15e2-4472-909e-47cb2cb584c2


New Issues (129) Checkmarx found the following issues in this Pull Request
# Severity Issue Source File / Package Checkmarx Insight
1 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 154
detailsThe web application's `clearCookies should remove all stored cookie configs` method creates a cookie Cookie, at line 154 of /app/src/test/kotlin/...
Attack Vector
2 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 148
detailsThe web application's `clearCookies should remove all stored cookie configs` method creates a cookie Cookie, at line 148 of /app/src/test/kotlin/...
Attack Vector
3 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/network/NetworkCookieManagerTest.kt: 203
detailsThe web application's Lambda method creates a cookie Cookie, at line 203 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/network/...
Attack Vector
4 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/network/NetworkCookieManagerTest.kt: 229
detailsThe web application's Lambda method creates a cookie Cookie, at line 229 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/network/...
Attack Vector
5 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/util/CookieConfigurationDataExtensionsTest.kt: 45
detailsThe web application's `toNetworkCookieList should map multiple cookies correctly` method creates a cookie Cookie, at line 45 of /app/src/test/kot...
Attack Vector
6 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/util/CookieConfigurationDataExtensionsTest.kt: 62
detailsThe web application's `toNetworkCookie should map name and value correctly` method creates a cookie Cookie, at line 62 of /app/src/test/kotlin/co...
Attack Vector
7 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/util/CookieConfigurationDataExtensionsTest.kt: 46
detailsThe web application's `toNetworkCookieList should map multiple cookies correctly` method creates a cookie Cookie, at line 46 of /app/src/test/kot...
Attack Vector
8 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/util/CookieConfigurationDataExtensionsTest.kt: 31
detailsThe web application's `toNetworkCookieList should map single cookie correctly` method creates a cookie Cookie, at line 31 of /app/src/test/kotlin...
Attack Vector
9 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 129
detailsThe web application's `storeCookieConfig with null should not affect other hostnames` method creates a cookie Cookie, at line 129 of /app/src/tes...
Attack Vector
10 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 123
detailsThe web application's `storeCookieConfig with null should not affect other hostnames` method creates a cookie Cookie, at line 123 of /app/src/tes...
Attack Vector
11 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 103
detailsThe web application's `storeCookieConfig with null should remove stored config` method creates a cookie Cookie, at line 103 of /app/src/test/kotl...
Attack Vector
12 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/CookieConfigurationDataExtensionsTest.kt: 32
detailsThe web application's `toAcquiredCookiesList should map list of Cookie to list of AcquiredCookie` method creates a cookie Cookie, at line 32 of /...
Attack Vector
13 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/AcquiredCookieExtensionsTest.kt: 39
detailsThe web application's `toConfigurationDataCookies should map list of AcquiredCookie to list of Cookie` method creates a cookie Cookie, at line 39...
Attack Vector
14 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/CookieConfigurationDataExtensionsTest.kt: 31
detailsThe web application's `toAcquiredCookiesList should map list of Cookie to list of AcquiredCookie` method creates a cookie Cookie, at line 31 of /...
Attack Vector
15 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/CookieConfigurationDataExtensionsTest.kt: 12
detailsThe web application's `toAcquiredCookie should map Cookie to AcquiredCookie` method creates a cookie Cookie, at line 12 of /app/src/test/kotlin/c...
Attack Vector
16 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/AcquiredCookieExtensionsTest.kt: 40
detailsThe web application's `toConfigurationDataCookies should map list of AcquiredCookie to list of Cookie` method creates a cookie Cookie, at line 40...
Attack Vector
17 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/repository/util/AcquiredCookieExtensionsTest.kt: 20
detailsThe web application's `toConfigurationCookie should map AcquiredCookie to CookieConfigurationData Cookie` method creates a cookie Cookie, at line...
Attack Vector
18 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/ServerCommunicationConfigRepositoryTest.kt: 72
detailsThe web application's Lambda method creates a cookie Cookie, at line 72 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/Se...
Attack Vector
19 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/ServerCommunicationConfigRepositoryTest.kt: 156
detailsThe web application's Lambda method creates a cookie Cookie, at line 156 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/S...
Attack Vector
20 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/ServerCommunicationConfigRepositoryTest.kt: 157
detailsThe web application's Lambda method creates a cookie Cookie, at line 157 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/S...
Attack Vector
21 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/ServerCommunicationConfigRepositoryTest.kt: 71
detailsThe web application's Lambda method creates a cookie Cookie, at line 71 of /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/sdk/Se...
Attack Vector
22 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 189
detailsThe web application's `storage should isolate configs by hostname` method creates a cookie Cookie, at line 189 of /app/src/test/kotlin/com/x8bit/...
Attack Vector
23 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 180
detailsThe web application's `storage should isolate configs by hostname` method creates a cookie Cookie, at line 180 of /app/src/test/kotlin/com/x8bit/...
Attack Vector
24 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 81
detailsThe web application's `storage should handle cookies with multiple values` method creates a cookie Cookie, at line 81 of /app/src/test/kotlin/com...
Attack Vector
25 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 85
detailsThe web application's `storage should handle cookies with multiple values` method creates a cookie Cookie, at line 85 of /app/src/test/kotlin/com...
Attack Vector
26 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 51
detailsThe web application's `storeCookieConfig should update existing config` method creates a cookie Cookie, at line 51 of /app/src/test/kotlin/com/x8...
Attack Vector
27 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 61
detailsThe web application's `storeCookieConfig should update existing config` method creates a cookie Cookie, at line 61 of /app/src/test/kotlin/com/x8...
Attack Vector
28 MEDIUM HttpOnly_Cookie_Flag_Not_Set /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/datasource/disk/CookieDiskSourceTest.kt: 32
detailsThe web application's `storeCookieConfig should persist config and getCookieConfig should retrieve it` method creates a cookie Cookie, at line 32...
Attack Vector
29 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 98
detailsMethod createMockCipherView at line 98 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user in...
Attack Vector
30 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryViewModelTest.kt: 203
detailsMethod Lambda at line 203 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/generator/passwordhistory/PasswordHistoryViewModelTest.kt s...
Attack Vector
31 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/addedit/AddEditSendViewModelTest.kt: 1202
detailsMethod Lambda at line 1202 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/addedit/AddEditSendViewModelTest.kt sends user inform...
Attack Vector
32 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 429
detailsMethod Lambda at line 429 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
33 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 386
detailsMethod Lambda at line 386 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
34 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 402
detailsMethod Lambda at line 402 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
35 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 334
detailsMethod Lambda at line 334 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
36 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 305
detailsMethod Lambda at line 305 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
37 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 265
detailsMethod Lambda at line 265 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
38 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 237
detailsMethod Lambda at line 237 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
39 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 206
detailsMethod Lambda at line 206 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
40 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 170
detailsMethod Lambda at line 170 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
41 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 110
detailsMethod Lambda at line 110 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest...
Attack Vector
42 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 90
detailsMethod Lambda at line 90 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest....
Attack Vector
43 MEDIUM Privacy_Violation /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest.kt: 70
detailsMethod Lambda at line 70 of /testharness/src/test/kotlin/com/bitwarden/testharness/ui/platform/feature/createpassword/CreatePasswordViewModelTest....
Attack Vector
44 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/exportitems/verifypassword/VerifyPasswordViewModelTest.kt: 482
detailsMethod Lambda at line 482 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/exportitems/verifypassword/VerifyPasswordViewModelTest.kt s...
Attack Vector
45 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 585
detailsMethod Lambda at line 585 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt se...
Attack Vector
46 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/vaultunlock/VaultUnlockViewModelTest.kt: 796
detailsMethod `on UnlockClick for password unlock should display error dialog on AuthenticationError` at line 796 of /app/src/test/kotlin/com/x8bit/bitw...
Attack Vector
47 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewModelTest.kt: 175
detailsMethod Lambda at line 175 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/deleteaccount/DeleteAccountViewM...
Attack Vector
48 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 61
detailsMethod Lambda at line 61 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user information outs...
Attack Vector
49 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 61
detailsMethod Lambda at line 61 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user information outs...
Attack Vector
50 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 125
detailsMethod createMockLoginView at line 125 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user in...
Attack Vector
51 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2CredentialAssertionRequestUtil.kt: 12
detailsMethod createMockFido2CredentialAssertionRequest at line 12 of /app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/model/Fido2CredentialAsser...
Attack Vector
52 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModelTest.kt: 150
detailsMethod `on ApproveAccountChangeClick dialog state should be cleared, user should be switched, and getAuthRequestByIdFlow should be called` at lin...
Attack Vector
53 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModelTest.kt: 376
detailsMethod Lambda at line 376 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewM...
Attack Vector
54 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewModelTest.kt: 307
detailsMethod Lambda at line 307 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/loginapproval/LoginApprovalViewM...
Attack Vector
55 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 446
detailsMethod Lambda at line 446 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt se...
Attack Vector
56 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 330
detailsMethod Lambda at line 330 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt se...
Attack Vector
57 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 362
detailsMethod Lambda at line 362 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt se...
Attack Vector
58 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 675
detailsMethod at line 675 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt sends us...
Attack Vector
59 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt: 687
detailsMethod at line 687 of /app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationViewModelTest.kt sends us...
Attack Vector
60 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 77
detailsMethod Lambda at line 77 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user information outs...
Attack Vector
61 MEDIUM Privacy_Violation /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt: 77
detailsMethod Lambda at line 77 of /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/datasource/sdk/model/CipherViewUtil.kt sends user information outs...
Attack Vector
62 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt: 147
detailsThe application uses the hard-coded password "cipherId1234" for authentication purposes, either using it to verify users' identities, or to access...
Attack Vector
63 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/attachments/AttachmentsViewModelTest.kt: 507
detailsThe application uses the hard-coded password "mockId-1" for authentication purposes, either using it to verify users' identities, or to access an...
Attack Vector
64 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/sdk/repository/SdkCipherRepositoryTest.kt: 205
detailsThe application uses the hard-coded password "cipherId" for authentication purposes, either using it to verify users' identities, or to access ano...
Attack Vector
65 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/tools/feature/send/addedit/AddEditSendViewModelTest.kt: 573
detailsThe application uses the hard-coded password "some-password" for authentication purposes, either using it to verify users' identities, or to acce...
Attack Vector
66 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/rootnav/RootNavViewModelTest.kt: 772
detailsThe application uses the hard-coded password "testPassword123" for authentication purposes, either using it to verify users' identities, or to acc...
Attack Vector
67 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/manager/VaultLockManagerTest.kt: 2011
detailsThe application uses the hard-coded password "mockValue" for authentication purposes, either using it to verify users' identities, or to access an...
Attack Vector
68 MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/data/vault/manager/VaultLockManagerTest.kt: 1955
detailsThe application uses the hard-coded password "mockValue" for authentication purposes, either using it to verify users' identities, or to access an...
Attack Vector

More results are available on the CxOne platform

@SaintPatrck SaintPatrck marked this pull request as ready for review March 31, 2026 18:46
@SaintPatrck SaintPatrck requested a review from a team as a code owner March 31, 2026 18:46
@SaintPatrck SaintPatrck requested a review from a team March 31, 2026 18:47
- `adb-capture.sh [--xml] [--screenshot] [--all]` - Capture current device state. Default (no flags): both screenshot and XML hierarchy.
- `adb-find-element.sh <text>` - Find element by `text` or `content-desc`, return center coordinates (`X Y`). Dumps UI hierarchy, parses XML, calculates center from bounds.
- `adb-tap-and-capture.sh <x> <y> [wait_seconds=2]` - Tap at coordinates, wait, capture and pull screenshot.
- `adb-tap-element.sh <text> [wait_seconds=2]` - Find, tap, and capture in one command (recommended). Combines `adb-find-element.sh` + `adb-tap-and-capture.sh`.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is getting too far into the weeds but are we at all concerned about z-order issues.

I know we have seen that in our own tests, where the FAB will be on top of another button, so when we click those coordinates, we expect the button clicked but we actually click the FAB.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I just ran into that. Claude figured out how to manually adjust the touch coordinates pretty quickly given the other instructions and commands that are present. I'll see if there's a relatively easy way to mitigate it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pivoted to an MCP server because the bash was getting crrraaaazy. This made handling z-order easier, and Claude is more likely to use them without direct instruction thanks to built-in MCP discovery. Converted the skill into an "instruction manual" for how to use the MCP server and perform common interactions. 🚀

Improve the reliability of automated UI interactions by verifying that the target element is the topmost clickable component at the calculated tap coordinates. This prevents "clickjacking" or failed interactions when the desired element is obscured by overlays, dialogs, or other UI containers.

- Implement a search within `view.xml` to identify the topmost clickable element at the target $(X, Y)$ coordinate, following the UIAutomator document order where the last element drawn is the one that receives the touch event.
- Add validation logic to determine if the topmost element matches the intended target based on text, content description, or identical boundary coordinates (supporting Compose parent wrappers).
- Introduce a new exit code `3` to signal that an element is obstructed, allowing callers to handle obscured states gracefully.
- Provide detailed diagnostic information to `stderr` when an obstruction is detected, including the text, resource ID, or package name of the obstructing element.
- Maintain backward compatibility by continuing to output the target center coordinates to `stdout`.
Replace 5 bash scripts with a TypeScript MCP server for Android device
interaction. The shell scripts hit limitations parsing dumpsys window
output and XML hierarchies with grep/awk (false positives on window
type matching, wallpaper frame detection, etc).

The MCP server uses:
- fast-xml-parser for UIAutomator XML hierarchy traversal
- Structured line-by-line dumpsys window parser with typed WindowInfo
- Native geometry types (Rect, Point) for obstruction detection
- Two-layer obstruction detection: system overlays via dumpsys touchable
  regions + in-app elements via XML topmost-clickable-at-point
- Visible region computation with 4-strip candidate selection

5 tools: capture, find_element, tap_at, tap_element, navigate
57 unit tests across geometry, parsers, and ADB discovery.
Designed for future promotion to ai-marketplace plugin.
Addresses code review feedback: find_element and tap_element shared ~30
lines of identical hierarchy dump + parse + obstruction detection logic.
New tool for typing text into focused fields via adb shell input text.
Escape $, backtick, and backslash in addition to double quotes before
passing text to adb shell. Without this, input like p@ss$WORD silently
expands the empty $WORD variable. Also fix stale .claude/mcp.json
reference in SKILL.md — file lives at .mcp.json (project root).
@SaintPatrck SaintPatrck changed the title [PM-34487] llm: Add interacting-with-android-device skill with ADB scripts [PM-34487] llm: Add Android device interaction MCP server with ADB tooling Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review-vnext Request a Claude code review using the vNext workflow t:llm Change Type - LLM related change (e.g. CLAUDE.md files)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants