Back to blog
mobileiOSAndroidsensitive data

Mobile local storage: why your app leaks secrets

Published on 2026-04-077 min readFlorian

The fundamental problem with mobile storage

Unlike a web application where sensitive data stays server-side, a mobile application often stores information locally: authentication tokens, user preferences, cached data, downloaded files. Every piece of data stored on the device is potentially accessible to an attacker with physical access or who exploits another vulnerability.

Android: storage pitfalls

Plaintext SharedPreferences

SharedPreferences are the most commonly used key-value storage on Android. By default, they're stored as unencrypted XML in /data/data/[package]/shared_prefs/. On a rooted device, these files are readable. We regularly find JWT tokens, API keys, and even passwords in these files.

Solution: use EncryptedSharedPreferences from the Jetpack Security library. Encryption is transparent to the developer.

Unencrypted SQLite databases

SQLite is used for structured storage. Without an encryption library like SQLCipher, databases are readable in plaintext. An adb pull on a rooted device or an unencrypted backup is enough to extract all the data.

Application logs

Log.d("auth", "Token: " + token) in debug mode that stays in production. Logs are accessible via adb logcat and can contain tokens, user data, or URLs with sensitive parameters.

WebView cache

WebViews cache HTML, cookies, and form data. If a WebView displays sensitive data, it can persist in the cache even after logout.

iOS: false friends of security

NSUserDefaults

The iOS equivalent of SharedPreferences. Stores in plaintext in a plist. This is not a secure location despite what many developers think. The data is in iTunes backups and accessible with forensics tools.

Misconfigured Keychain

The iOS Keychain is secure by design but its protection level depends on configuration. The kSecAttrAccessibleAlways attribute makes data accessible even when the device is locked. The correct attribute for most cases is kSecAttrAccessibleWhenUnlockedThisDeviceOnly.

Clipboard

The iOS clipboard is shared between all applications. If the user copies a password or 2FA code, any background application can read it. Since iOS 16, the user is warned but access remains possible.

Background snapshots

When an application goes to the background, iOS captures a screenshot for the transition animation. If the screen displays sensitive data (bank balance, medical information), this image is stored on the device.

What we find in audits

In our analyses, we frequently find:

  • OAuth refresh tokens stored in SharedPreferences/NSUserDefaults
  • Third-party API keys (Stripe, Firebase, AWS) in plaintext in code or local storage
  • Complete user data in SQLite cache (names, emails, phone numbers)
  • Browsing history and form data in WebView cache
  • Client certificates and private keys in the application bundle
  • Ground rules

  • Only store what's necessary: every stored piece of data is a risk. Prefer fresh API calls over local caches for sensitive data
  • Use native secure storage: Keychain on iOS, EncryptedSharedPreferences on Android
  • Encrypt SQLite databases: SQLCipher for Android, the SQLite encryption library for iOS
  • Clean up on logout: delete all local files, caches, cookies, and session data
  • Mask the screen in background: display a replacement screen when the application goes to background
  • Request a free CleanIssue diagnostic to audit your mobile application's local storage.

    Related articles

    Three adjacent analyses to keep exploring the same attack surface.

    Sources

    Written by Florian
    Reviewed on 2026-04-07

    Editorial analysis based on official vendor, project, and regulator documentation.

    Related services

    If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.

    Need an external review of your HR SaaS?

    Share your product, stack, and client context. We will come back with the right review scope.

    Discuss your audit