Skip to content

fix(android): keep the API bearer token out of device backups#1306

Open
sh1nj1 wants to merge 1 commit into
mainfrom
fix/android-token-at-rest
Open

fix(android): keep the API bearer token out of device backups#1306
sh1nj1 wants to merge 1 commit into
mainfrom
fix/android-token-at-rest

Conversation

@sh1nj1

@sh1nj1 sh1nj1 commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

Daily code scan finding (code-scan-2026-06-15) on the freshly merged Voice Companion (#1297). The Android companion stores its Doorkeeper bearer token — which grants full mobile-API access to the user's Collavre account (approve/deny permission prompts, post comments as the user, register devices) — in the collavre_voice Preferences DataStore (SettingsRepository). That file is app-private but plaintext, and the manifest shipped with android:allowBackup="true" (the platform default).

That combination means Android Auto Backup (uploads app-private files to the user's cloud) and adb backup can exfiltrate the token in cleartext — a credential-at-rest exposure (CWE-312 Cleartext Storage of Sensitive Information, OWASP MASVS-STORAGE-2 no sensitive data in backups).

Fix

  • android:allowBackup="false" — blocks Auto Backup and adb backup on all API levels.
  • Add android:dataExtractionRules excluding the file/sharedpref/database domains. On Android 12+ (this app targets SDK 34), backup and device-to-device transfer are governed separately from allowBackup, so without this a D2D migration could still copy the token. The DataStore lives in the file domain, so it is now excluded from both channels.

Scope / risk

Manifest + one new XML resource only. No Kotlin, no server code, no test impact. Loses cloud backup of the handful of non-sensitive UI prefs (TTS rate, locale) — an acceptable trade since they all live in the same single datastore as the token and can't be excluded at sub-file granularity.

Follow-up (not in this PR)

A defense-in-depth hardening would move the token specifically into EncryptedSharedPreferences / a Keystore-backed key so it is encrypted at rest even within the app sandbox. Left as a follow-up to keep this fix minimal and unambiguous.

The voice companion stores its Doorkeeper bearer token — which grants full
mobile-API access to the user's Collavre account — in the collavre_voice
Preferences DataStore. That file is app-private but plaintext, and the manifest
shipped with allowBackup="true" (the default), so Android Auto Backup and
adb backup could exfiltrate the token in cleartext (CWE-312, OWASP
MASVS-STORAGE-2).

Set allowBackup="false" to block Auto Backup / adb backup on all versions, and
add dataExtractionRules excluding the file/sharedpref/database domains so a
device-to-device transfer on Android 12+ (governed separately from allowBackup)
also can't copy the token.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant