Skip to content

feat(android): warn user when third-party accessibility service active before seed phrase reveal#20971

Open
xAlisher wants to merge 1 commit into
masterfrom
feat/a11y-service-warning-20965
Open

feat(android): warn user when third-party accessibility service active before seed phrase reveal#20971
xAlisher wants to merge 1 commit into
masterfrom
feat/a11y-service-warning-20965

Conversation

@xAlisher
Copy link
Copy Markdown
Contributor

Closes #20965

What this does

Before revealing the recovery phrase, check whether any third-party accessibility service is active on the device. If so, show an informed-consent dialog that:

  • Lists the service names in a bulleted list (e.g. "ChatGPT screen help", "Link to Windows")
  • Links directly to Settings > Accessibility so the user can disable services they don't trust
  • Offers Cancel (stays hidden) or Reveal anyway (proceeds with reveal)

If no third-party services are active, reveal proceeds without interruption.

This applies to both the Settings → Back up recovery phrase flow (BackupSeedphraseReveal.qml) and the onboarding seed phrase display flow (SeedPhrase.qml).

Implementation

Java (Android)

  • AccessibilityServiceHelper.java — new class; queries AccessibilityManager for enabled services, filters out system/OEM packages (com.android.*, com.google.*, com.samsung.*, com.sec.*) and the app's own package.
  • StatusQtActivity.java — adds getThirdPartyA11yServices() instance method and openAccessibilitySettings() static method, both callable from C++ via JNI.

C++ (StatusQ)

  • systemutilsinternal.h/cpp — exposes activeThirdPartyA11yServices() and openAccessibilitySettings() as Q_INVOKABLE through SystemUtils singleton. Uses QtNative.activity() + callObjectMethod pattern (required for Qt 6.11 — callStaticObjectMethod returning jobject with no arguments has a known varargs issue).

QML

  • AccessibilityWarningPopup.qml — new StatusDialog using existing design tokens; bulleted service list; Settings > Accessibility deep-link via onLinkActivated.
  • BackupSeedphraseReveal.qml, SeedPhrase.qml — reveal button onClicked gates on SystemUtils.activeThirdPartyA11yServices(); opens popup if non-empty, reveals directly otherwise.

Test steps

  1. Enable a third-party accessibility service (e.g. ChatGPT Screen Help)
  2. Settings → Back up recovery phrase → Reveal recovery phrase → warning popup appears listing the service
  3. Tap Settings > Accessibility link → opens Android Accessibility Settings
  4. Tap Cancel → popup closes, phrase stays hidden
  5. Tap Reveal again → popup → Reveal anyway → phrase appears
  6. Disable all third-party accessibility services → tap Reveal → no popup, phrase reveals directly

Screenshots

Related

…seed phrase reveal

Closes #20965

Before revealing the recovery phrase, check whether any third-party
accessibility service is active. If so, show an informed-consent dialog
listing the service names, with a link to Android Accessibility Settings
and a "Reveal anyway" / "Cancel" choice.

Implementation:
- AccessibilityServiceHelper.java: queries AccessibilityManager for
  enabled services, filters out system/OEM packages (com.android.*,
  com.google.*, com.samsung.*, com.sec.*) and the app itself.
- StatusQtActivity.java: adds getThirdPartyA11yServices() instance
  method (JNI bridge) and openAccessibilitySettings() static method.
- systemutilsinternal.cpp/h: exposes both methods as Q_INVOKABLE via
  QJniObject — uses QtNative.activity() + callObjectMethod pattern to
  avoid Qt 6.11 varargs issue with callStaticObjectMethod returning
  jobject.
- AccessibilityWarningPopup.qml: new StatusDialog with bulleted service
  list and a deep-link to Settings > Accessibility.
- BackupSeedphraseReveal.qml, SeedPhrase.qml: reveal button onClicked
  gates on activeThirdPartyA11yServices(); opens popup when non-empty,
  reveals directly otherwise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@status-im-auto
Copy link
Copy Markdown
Member

status-im-auto commented May 20, 2026

Jenkins Builds

Click to see older builds (11)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ c616fee 1 2026-05-20 11:24:45 ~12 min macos/aarch64 🍎dmg
✔️ c616fee 1 2026-05-20 11:35:12 ~22 min tests/nim 📄log
✔️ c616fee 1 2026-05-20 11:41:36 ~29 min linux/x86_64 📦tgz
✔️ c616fee 1 2026-05-20 11:43:06 ~30 min tests/ui 📄log
✔️ c616fee 1 2026-05-20 11:50:52 ~38 min windows/x86_64 💿exe
✔️ c616fee 11341 2026-05-20 12:24:02 ~42 min tests/e2e 📊rpt
✖️ c616fee 3493 2026-05-27 05:47:13 ~15 min tests/e2e-android 📦pkg
✔️ eb27cba9 2 2026-05-22 05:30:05 ~11 min android/arm64 🤖apk 📲
✔️ 7389eadd 3 2026-05-23 05:29:00 ~10 min android/arm64 🤖apk 📲
✔️ 74a32a51 4 2026-05-26 05:28:47 ~10 min android/arm64 🤖apk 📲
✔️ 220f2892 5 2026-05-27 05:31:50 ~13 min android/arm64 🤖apk 📲
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 4b600bf6 6 2026-05-29 05:32:23 ~13 min android/arm64 🤖apk 📲
✔️ 372d3ccc 7 2026-06-02 05:32:04 ~13 min android/arm64 🤖apk 📲

@caybro
Copy link
Copy Markdown
Member

caybro commented May 20, 2026

@xAlisher some screenshot or video of the PR in action would be nice :)

@xAlisher
Copy link
Copy Markdown
Contributor Author

@caybro here it is

#20965 (comment)

Copy link
Copy Markdown
Contributor

@alexjba alexjba left a comment

Choose a reason for hiding this comment

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

Awesome!
Just some suggestions/questions.

Didn't test it though. I can give it a spin tomorrow

* Returns a comma-separated list of active third-party accessibility service names,
* or an empty string if none are found.
*
* Filters out known system/OEM packages (com.android.*, com.samsung.*, com.sec.*,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm, why skipping these? I imagine this list is incomplete. If we need to skip Samsung packages, it would probably make sense to include all the other big OEM flavors.

Would it hurt not to skip any of these apps?

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.

Thanks for highlighting it! Yep, it's easy to prepare this list.

But it's more of a strategic than functional decision. Personally I'd be in favour of notifying about all accessibility apps and letting the user decide if they're OK to let Samsung's or whatever Xiaomi's apps access their recovery phrase. From a purist privacy-maxi standpoint this is the only way forward.

Curious what @sunleos thinks — would you be OK with listing all of them and letting the user decide?

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.

Agreed with @sunleos to show all apps.

@@ -0,0 +1,49 @@
package app.status.mobile;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd place all this in the MobileUI repo. It would be exposed to QML directly by MobileUI package. It would mostly mean to move the code there.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure... we need to call it from our C++ internal utils, not directly from QML

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But not necessarily probably

Comment on lines +46 to +47
String r = String.join(", ", names);
return r;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
String r = String.join(", ", names);
return r;
return String.join(",", names);

would work better I guess, ie w/o the space in between

@@ -0,0 +1,49 @@
package app.status.mobile;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure... we need to call it from our C++ internal utils, not directly from QML

@@ -0,0 +1,49 @@
package app.status.mobile;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But not necessarily probably

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants