Technical guide

How to protect Android and iOS apps from keylogging malware

Protect typed secrets from keylogging: Android accessibility malware checks, sensitive views, keyboard flags, in-app PIN pads and iOS secure text entry.

  • Reduce what is typed

    Fewer typed secrets means less to capture. Use passkeys, biometrics and in-app PIN pads where the journey allows.

  • Harden each platform

    Android needs accessibility and keyboard controls; iOS needs secure text entry and a keyboard extension policy. Test each on its own.

  • Keep assistive tools working

    Screen readers, password managers and approved keyboards must still complete the journey. Respond to evidence, not to installed tools.

To protect Android and iOS apps from keylogging malware, cut the number of secrets people type, harden every sensitive field, and watch for the components that can read input. On Android, the main threat is not a classic keylogger but malware that abuses accessibility services to read screens and keystrokes, so check enabled services and mark sensitive views. Both platforms let third-party keyboards see what is typed in ordinary fields. iOS replaces them with the system keyboard for secure text entry, and Android can ask keyboards not to learn. This guide covers Android and iOS separately.

Where typed secrets leak

Map one journey, such as sign-in or a payment confirmation. Note where text enters the app, which component receives it and where it goes next. On mobile, typed input can leak through four routes:

RouteAndroidiOS
Accessibility abuseA malicious accessibility service reads view text and input eventsNo equivalent API for third-party apps
Third-party keyboardAn input method sees every key in fields it servesA keyboard extension sees ordinary fields; with Full Access it can use the network
Hooked app processInjected code reads fields or memory, usually on rooted devicesInjected code reads fields or memory, usually on jailbroken devices
The app itselfLogs, analytics, crash reports and clipboardLogs, analytics, crash reports and clipboard

Close the last route first. No raw input, clipboard content or token should reach logs or analytics. It is the most common leak and the easiest to fix.

Android: accessibility malware

Banking trojans on Android commonly ask the user to enable an accessibility service. Once enabled, the service can read the text of on-screen views, observe input events and perform taps. That gives the attacker keystrokes without a keyboard.

Check enabled services

AccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) returns the services that are currently enabled. For each one you can read its package, its declared capabilities and whether it declares isAccessibilityTool, the flag for services built to assist people with disabilities. Compare the list with what you expect: screen readers and switch access are legitimate; a newly installed app with no assistive purpose is a strong risk signal. Re-check when the app returns to the foreground, because malware is often enabled mid-session.

Mark sensitive views

On Android 14 (API level 34) and later, call View.setAccessibilityDataSensitive(View.ACCESSIBILITY_DATA_SENSITIVE_YES), or set android:accessibilityDataSensitive in the layout, on password fields, PIN pads and confirmation screens. Only services that declare isAccessibilityTool can then read or act on those views. Genuine screen readers keep working; a malicious service that does not declare the flag is cut out of that view.

Know the platform barrier

Android 13 added restricted settings. For many apps installed outside an app store, such as an APK downloaded through a browser, the system blocks accessibility and notification listener access until the user explicitly allows restricted settings in the app’s info screen. Attackers now coach victims through that step, so treat the barrier as friction, not protection.

For the full control, see Android accessibility malware. Overlays that trick users into typing into a fake screen are covered on Android overlay attack detection.

Android: input hardening

  • Password fields. Use inputType="textPassword" (or numberPassword) on the actual field. It conceals characters and keyboards treat it as sensitive, but the keyboard still receives every key.
  • No learning. Add EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING to imeOptions on sensitive fields. It asks the keyboard not to store typing history or update its language model. It is a request; a malicious keyboard can ignore it.
  • No suggestions. Use textNoSuggestions on fields such as account numbers or one-time codes so values do not appear in suggestion strips.
  • In-app PIN pads. For PINs and transaction codes, a custom keypad drawn by the app keeps digits away from third-party keyboards. Mark it sensitive for accessibility, give each key a content description for screen readers, and set filterTouchesWhenObscured so taps are refused when another window covers it.
  • Framework fields. In Flutter and React Native, confirm in the release build that the rendered native field carries the intended input type and flags.

iOS: keyboards and secure entry

iOS has no system-wide accessibility API for third-party apps, so the focus is the keyboard and the app process.

  • Secure text entry. Set isSecureTextEntry on password and PIN fields. iOS replaces any custom keyboard with the system keyboard while that field is active.
  • Reject keyboard extensions. For high-risk apps, implement application(_:shouldAllowExtensionPointIdentifier:) in the app delegate and return false for .keyboard. All third-party keyboards are then replaced by the system keyboard in your app. Test the effect on people who rely on a language or assistive keyboard before you ship it.
  • Full Access. A keyboard extension needs the user to grant Full Access before it can use the network. A keyboard with Full Access in a non-secure field can send what it sees.
  • Autofill. Set textContentType to .password, .newPassword or .oneTimeCode so password managers and AutoFill work, which reduces typing.
  • Ordinary fields. For account numbers and similar values in non-secure fields, set autocorrectionType and spellCheckingType to .no.

Separate guidance for each platform is on Android app security and iOS app security.

Detect, then respond

Otukan detects accessibility services and overlays that can read or drive your app’s screens on Android, and detects hooking and tampering in the app process on Android and on iOS. The evidence goes to your backend with the request it concerns, and the app applies the response you set for each flow: observe, warn, restrict or terminate. For the product view, see keylogging detection.

Base the response on the action at stake:

  • Weak evidence (an unfamiliar keyboard in an ordinary field): record it, change nothing for the user.
  • Medium evidence (a non-assistive accessibility service enabled during a payment): step up with a factor that is not typed, such as a biometric or a passkey.
  • Strong evidence (hooking in the app process during sign-in): pause the sensitive action and offer a supported route.

Never ask the person to re-type a secret while the risky condition is still present. Explain the action without accusing them.

Test the journey

  1. Use a dedicated device, a test account, a non-production backend and synthetic credentials.
  2. Run the journey clean, with the system keyboard, a screen reader and a password manager. Record the outcome.
  3. Enable an authorised test accessibility service that reads view text. Confirm sensitive views are hidden from it from Android 14, and that the app reports it.
  4. On iOS, install a test keyboard extension with Full Access and confirm it is replaced in secure fields and, if you reject extensions, in every field.
  5. Remove the test conditions and repeat. No stale restriction should remain.

Release checklist

  • Logs, analytics and crash reports contain no typed input or clipboard content.
  • Android sensitive views are marked accessibility-data-sensitive.
  • Sensitive Android fields use the right input type and no-learning flag.
  • iOS secure fields use secure text entry; the keyboard extension policy is a recorded decision.
  • Screen readers, switch access and password managers complete the journey.
  • Each platform’s test record names the build, OS version and tester.

Further reading

Common questions

  • What is the main keylogging threat on Android?

    Malware that abuses accessibility services, not a classic keylogger. An enabled malicious service can read on-screen text, observe input events and perform taps. Check enabled services with AccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) and re-check when the app returns to the foreground, because malware is often enabled mid-session.

  • Does setAccessibilityDataSensitive stop screen readers working?

    No. On Android 14 (API level 34) and later, View.setAccessibilityDataSensitive(View.ACCESSIBILITY_DATA_SENSITIVE_YES) lets only services that declare isAccessibilityTool read or act on the view. Genuine screen readers keep working, while a malicious service that does not declare the flag is cut out of that view.

  • Does IME_FLAG_NO_PERSONALIZED_LEARNING stop a malicious Android keyboard?

    No. It asks the keyboard not to store typing history or update its language model, but it is a request and a malicious keyboard can ignore it. textPassword conceals characters, yet the keyboard still receives every key. For PINs and transaction codes, an in-app keypad keeps digits away from third-party keyboards.

  • Can an iOS app keep third-party keyboards out of its fields?

    Yes. With isSecureTextEntry, iOS replaces any custom keyboard with the system keyboard while that field is active. For high-risk apps, returning false for .keyboard in application(_:shouldAllowExtensionPointIdentifier:) replaces all third-party keyboards in your app. Test the effect on people who rely on a language or assistive keyboard first.

  • How should the app respond to keylogging evidence?

    In proportion to the evidence and the action at stake. Record an unfamiliar keyboard in an ordinary field without changing anything, step up with a non-typed factor when a non-assistive accessibility service is enabled during a payment, and pause the action for hooking during sign-in. Never ask for a secret to be re-typed meanwhile.

Test the sensitive input journey

Tell us your platforms, framework and sensitive input journey, including accessibility requirements. We never ask for binaries, credentials, signing keys or production input data.

Or request a technical demo