← Back to blog
TR

2026-04-30 · 6 min

Sensitive data in iOS app memory: what to check after logout (2026)

What memory residue is, why OWASP dropped its memory test, and why storage and caches matter more after logout. A practical before/after check for the iOS Simulator.

Quick summary

  • • Holding a token in memory during the session is normal; what matters is what is still reachable after logout.
  • • OWASP deprecated MASTG-TEST-0060 (memory); residue after logout is tracked as MASWE-0024.
  • • Check storage and caches first, then memory, and compare before and after logout.

What “memory residue” means

When a user logs out, the session token, the refresh token and personal data should stop being reachable by the app. Residue is anything still there afterwards: a copy in a view model or a singleton, a response in the URL cache, a value in UserDefaults or a row in SQLite.

A copy in memory during the session is not a vulnerability. Every app that uses bearer authentication holds its access token while the user is signed in. The question is what happens after the session ends.

Why storage comes before memory

OWASP's MASTG deprecated its memory test (MASTG-TEST-0060): reading another process's memory needs a jailbroken device or a debug build, and pentesters usually rate memory-only findings Low. Storage is different. A token in Cache.db or a plist survives a restart and can end up in backups.

Our benchmark app showed the same pattern: the survivors a pentester would write up were in caches and storage (Cache.db, UserDefaults, SQLite), while memory added a JWT copy held by Foundation's URL loading.

A before/after check

1. Log in and open the screens that handle secrets. 2. Capture the app's memory and its Simulator container. 3. Log out. 4. Capture again and compare: what survived, what appeared, what was released.

Match values by a keyed hash, not by address or file name: a token that moved from the heap to Cache.db is still the same token.

Only trust a clean result if the capture read most of the app's writable memory. A scan that read a quarter of it and found nothing proves nothing.

Common fixes on iOS

Use URLSessionConfiguration.ephemeral (or Cache-Control: no-store) for authenticated requests, and clear URLCache.shared on logout.

Keep tokens in the Keychain, not in UserDefaults or @AppStorage, and delete the Keychain items on logout.

Drop session objects on logout: release the shared session store and cancel tasks that captured the token.

Very short strings (up to about 11 characters, such as a PIN) can live inside tagged pointers and are invisible to any memory scan. Don't rely on a memory scan for those.

How WatchMemory does it

WatchMemory runs this check on the iOS Simulator. It captures memory and storage before and after logout, groups results per secret, names the store and key, and returns PASS, FAIL or INCOMPLETE (coverage below 90 %).

Memory-only survivors fail the gate only when the result is reliable: native code with MallocScribble on, so freed memory is overwritten. It automates the OWASP MASWE-0024 check; it doesn't certify anything.

FAQ

Is a token in memory during the session a problem?

No. Apps need their access token while the user is logged in. Residue testing is about what is still reachable after logout, account switch or account deletion.

Can WatchMemory scan an App Store build?

No. It checks debug builds you run on the Simulator (and debuggable Android builds in the beta). The OS doesn't let anyone attach to a release build without the same access.

For more guides, visit WatchMemory Blog.

WatchMemory's Mac app is local-first: scans stay on your machine. Web analytics are privacy-friendly and used only to improve the website.