Repository navigation
feat(android): add optional private comparison for secure input #2289
Description
Activity
Triage: the feasibility evidence is useful and the privacy/freshness constraints are directionally sound, but this is deliberately not implementation-ready. It first needs a maintainer decision on whether agent-device should expose a cross-platform secure-value comparison capability and, if accepted, an owning shared contract plus threat-model review. Marking needs-triage rather than ready-for-agent; no reporter information is currently missing.
Proposed contract for discussion
Thanks for clarifying the triage boundary. This is a design proposal for the capability decision and shared contract, rather than an implementation request.
The attached sketch summarizes an optional secure-field comparison capability. Field metadata and masked text can describe an editor, but cannot establish whether its complete contents equal an expected value.
Proposed result semantics
Outcome Meaning matchA fresh, complete read of the bound target equals the authorized expected value. mismatchA fresh, complete read of that target differs, including when the lengths are identical. unknownEquality cannot be established because support, authorization, completeness, freshness or target identity is missing. These outcomes describe field equality only. They do not establish that an application accepted a value or completed a workflow.
Constraints for the shared contract
- Keep observed text inside the trusted platform adapter. Deliver the expected value through a protected channel, excluding it from ordinary CLI arguments, logs, traces, errors and artifacts. Return only the outcome, a bounded reason and minimal non-secret provenance; omit value length by default.
- Bind each request and response to the device, session, application, editor identity/generation and a fresh nonce. A focus or ownership change invalidates the comparison. Reject stale or replayed responses.
- Require a complete, fresh read. Partial or truncated content cannot establish either match or mismatch. A known complete empty value can be compared; an unavailable read cannot.
- Make support discoverable per adapter. Unsupported platforms and editors return
unknownwith an explicit reason. A shared contract does not require every platform to implement the capability immediately. - Require explicit authorization and bounded requests. Even an equality-only response can become a guessing oracle; the threat model should cover who may supply expectations, attempt limits, and transport access.
- Bound read sizes, execution time and cleanup. Restore any temporarily changed input-method configuration on close or failure.
Suggested acceptance cases
Matching and different same-length values; complete empty values; focus changes; editor recreation; stale sessions and nonces; partial/truncated/refused reads; unsupported adapters; timeout/cancellation; and synthetic sentinel checks across all output and error paths.
Before implementation, could we agree on:
- Whether this optional capability belongs in agent-device.
- Who should own the shared contract and threat-model review.
- The expectation transport, authorization model, and minimum conformance requirements for a first adapter.
This sketch is illustrative.

Decision: deferred, decided together with #3260, #3261 and #3106.
#2290 (metadata) merged, but a private comparison needs pieces nobody owns yet: how the expected value reaches the device without argv (#3260 lands first), what the comparison may disclose (match/mismatch/unknown only, no length leak), binding to the target, focus and input-connection generation, and treating partial or stale reads as unknown. Pick this up once #3260 has merged and someone owns that contract. Until then, Android
fillon secure fields stays unverified rather than compared.- addedbacklogLower priority / backlogLower priority / backlogand removedneeds-triageNew or unreviewed issueNew or unreviewed issue
on Oct 9, 2026
Add optional native private input comparison for secure fields
Android secure fields can expose masked accessibility text even after a successful
fill. Preserving password, hint, selection and mask metadata improves evidence,
but metadata alone cannot prove the exact value was entered. The existing Android
IME helper commits and clears input; it does not currently provide private
readback/comparison evidence.
Reproduction and bounded evidence
A disposable API 36 emulator ran a native synthetic EditText fixture and a
diagnostic IME in separate application processes. After public agent-device fill
with synthetic 2468, the secure node reported
password:trueand accessibilitymask_onlytext of length 4. The IME's InputConnection extracted text reportedlength 4 and equality true against that fixed synthetic expectation. Filling a
different same-length synthetic value, 1357, produced length 4 and equality false.
The observed extraction had startOffset 0 and partialStartOffset/partialEndOffset
-1. Retrieved text was compared in-process and never printed.
This establishes a narrow native feasibility result on that fixture and device.
It does not establish support for every app, WebView, custom editor, Android
version, or another platform.
The fixture uses
EditTextwithTYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORDand
PasswordTransformationMethod.getInstance(). The separate diagnostic IMEcalls
getCurrentInputConnection().getExtractedText(request, 0)and comparesextracted.textto the fixed synthetic expectation in-process. This is a probe,not the proposed production protocol: fragment equality alone cannot establish
complete, target-bound field equality.
Proposed capability
Add an optional private comparison operation through the existing Android IME
helper, returning a structured
match,mismatch, orunknownresult. Keep rawfield text inside the native helper. This should supplement fill evidence without
making accessibility masks an exact-value assertion.
The operation should require:
focused target, and input-connection generation. Bind the expectation and reply
to a fresh nonce; reject focus or generation changes during capture/comparison.
partial-update markers, and prove completeness within bounded reads. A cursor
fragment, stale extraction, truncation, or unavailable completeness signal must
yield unknown, even if a returned fragment matches.
connections, unsupported editors, timeouts, and uncertain ownership return
explicit unknown/unsupported reasons rather than success or empty-value claims.
ownership checks. Preserve existing guards against typing into the IME itself.
Restore prior IME configuration when a session ends or fails.
serialize raw retrieved values or expected secrets into evidence. Return only
the comparison result and minimal non-sensitive provenance needed to validate
freshness; do not expose lengths by default unless separately justified.
Expose this as a platform capability through the shared tool contract: callers
must be able to discover support and handle unknown consistently on Android, iOS,
and web. Do not imply an Android IME implementation automatically supplies iOS or
web parity. Unsupported platforms should retain truthful evidence limitations.
Acceptance checks
outcomes on a genuinely masked native field.
stale sessions, partial extraction, truncation, and refusal cannot produce a
false match.
values, including failure paths.
checkpoint to exact-value success.
This issue proposes a capability boundary and validation work, not a production
ready implementation or universal support claim. A metadata-only change remains
useful independently but does not close the exact-comparison gap.