Introduction
Mobile apps often handle sensitive data daily, such as credentials, tokens, health records, financial information, and personal identifiers that attackers seek to exploit.
On iOS, developers sometimes assume local data storage is inherently secure because of sandboxing and built-in Apple protections. This assumption is flawed.
Poorly implemented storage practices can expose critical data, leading to severe privacy and security incidents.
This article examines
- How insecure local data storage occurs in iOS applications,
- The specific risks across different storage mechanisms, and
- The technical countermeasures that developers and security teams must adopt to mitigate these threats.
Key takeaways: Securing iOS local storage
- Local storage is not inherently safe. iOS sandboxing isn’t enough. Attackers can still extract sensitive data with basic forensic tools.
- NSUserDefaults is a trap. Never store passwords, tokens, or keys in NSUserDefaults, as it saves data in plaintext plist files.
- Use Keychain the right way. Stick to SecAttrAccessibleWhenUnlockedThisDeviceOnly or stricter; avoid Always attributes.
- Encrypt all databases. SQLite (with SQLCipher), Realm, and Couchbase Lite all require explicit encryption setup. Defaults are insecure.
- Don’t trust logs & caches. Remove sensitive data from logs, disable predictive keyboard caching, and prevent iOS screenshots from capturing private views.
- Follow MASVS & Apple’s guidelines. Map your app’s storage strategy against OWASP MASVS and Apple’s official data protection rules to avoid compliance gaps.
- Defense-in-depth is mandatory. Combine keychain, database encryption, and logging/caching controls to close the most common exploit paths.
Understanding insecure data storage in iOS apps
Insecure data storage refers to storing sensitive information on a device without strong protection.
Attackers with device access—physical theft, malware, or remote compromise—can extract this data using forensic tools, jailbreak techniques, or even basic device backups. Once retrieved, the data may allow account takeover, identity theft, or further lateral movement.
Factors contributing to insecure storage
The primary contributors to insecure storage are:
- Saving unencrypted data in plaintext containers
- Relying on weak or default encryption configurations
- Storing excessive logs or cached information unnecessarily
- Ignoring secure APIs and platform guidelines
Data storage in iOS
In iOS applications, data can be stored in various locations, including:
- NSUserDefaults
- Unsecured Keychains data
- SQLite Databases
- CoreData
- Yap Database
- Couchbase Lite Databases
- Background caching of screenshots
- Logging
Risks in common iOS data storage mechanisms
NSUserDefaults
NSUserDefaults provides a convenient way for iOS applications to store user preferences and lightweight data, but it has significant security vulnerabilities if misused.
Risks in using NSUserDefaults
Many developers inadvertently store sensitive information, such as authentication credentials, API keys, or personally identifiable information (PII), in NSUserDefaults, not realizing that this data is stored in an unencrypted property list or plist file located in the application’s ”/Library/Preference/“ directory.
Moreover, the data stored in NSUserDefaults is not protected by iOS keychain services, making it vulnerable to unauthorized access and manipulation, particularly on jailbroken devices.
If an attacker were to access this file, they could potentially steal user credentials, modify application settings, or bypass established security protocols.
Secure approach
Tools like iExplorer or simple device backups can extract this data within seconds.
Unsecured Keychains data
Sensitive data can be exposed in a keychain with inappropriate accessibility settings. While Apple’s Keychain is the recommended place for storing sensitive credentials, improper configuration undermines its security.
Risks in unsecured keychain data
Developers often use kSecAttrAccessibleAlways, which keeps items available even when the device is locked, creating exposure. Weak access controls or misconfigurations in group sharing can also allow data leakage between apps.
SQLite databases
SQLite is an open-source SQL database that stores data in a text file on a device. It supports all the features of a relational database and is widely used for structured app data.
Storing sensitive data, such as user credentials, session tokens, and API keys, can expose this data to other applications or a superuser, as no authentication is required to access it.
Risks in SQLite databases
Unencrypted SQLite files are easily extracted using forensic tools. Metadata, query history, and complete records—including PII or financial details—can be recovered.
The SQLite engine does not have built-in security to protect databases. Instead, it relies on its environment, such as the operating system, to provide security for database content.
Secure approach
All data being stored in the database must be verified and secured.
CoreData
Core Data is a framework for managing the model layer of objects in your application. It serves as a means for applications to store data for use in subsequent stages of operation.
Risks in CoreData
CoreData is often backed by SQLite. These databases do not have built-in encryption features, meaning all information is stored in plain text within the files.
As a result, if an application saves user credentials or other sensitive personal information in this database, it is vulnerable to unauthorized access. Attackers can traverse schema and entity relationships, reconstructing user activity or private content.
Realm databases
The Realm databases are stored as files with the .realm extension, and they are located within the file system at the specific path:
/Application/Containers/Data/Application//Documents/default.realm
This path is part of the app’s sandboxed environment on iOS devices, which is designed to isolate app data from other applications.
However, on jailbroken devices, this sandboxing can be bypassed, allowing malicious actors to navigate the file system and access these .realm files directly.
Risks in Realm databases
Realm databases store data in a binary format, but without enabling built-in encryption, the files remain unprotected. Attackers with file system access can parse these files.
Developers may neglect Realm’s encryptionKey configuration, leaving the database equivalent to plaintext.
Yap Database
YapDatabase is a high-performance, key-value database for iOS and macOS applications, often used as an alternative to Core Data or Realm. YapDatabase offers robust features, including caching, automatic serialization, and multithreading.
As a result, if an application uses this database to store user credentials or other sensitive information, such data could be at risk of being accessed by unauthorized third parties.
Risks in the Yap database
By default, the Yap database stores data in plain text. Sensitive objects stored here can be extracted directly.
Without explicit encryption layers, Yap provides no inherent guarantees of confidentiality.
Couchbase Lite databases
Couchbase Lite is a compact, embedded, document-oriented (NoSQL) database engine that supports synchronization. Couch databases serve as storage solutions for applications, allowing them to retain data for future use. The files associated with the database, particularly those that carry the “.cblite” extension.
Risks in Couchbase Lite databases
These databases lack integrated encryption capabilities, resulting in all stored information being in plain text.
If developers skip implementing the database’s full encryption API, local documents—including offline caches—remain fully exposed. The sensitive data in this application’s database is, therefore, vulnerable to unauthorized access.
Caching of Screenshots
When an iOS app moves to the background, the operating system captures a screenshot of the current user interface to ensure a smooth return to the app.
While this feature enhances the user experience, it can raise security issues if sensitive information, such as financial details, personal data, or authentication screens, appears in the background image.
The cached screenshots are located within the file system at the specific path:
/Application/Containers/Data/Application//Library/SplashBoard/Snapshots/sceneID:*/
Security issues with the caching of screenshots
iOS captures app screenshots for fast app switching. These images may inadvertently include sensitive data like transaction details, OTPs, or chat messages.
Without mitigation, screenshots are stored unprotected and can be extracted from device backups or memory dumps.
Logging
NSLog is an essential function for iOS developers, widely used to debug iOS applications. It enables developers to check variable values, record essential notes, and pinpoint errors when a debugger isn’t available.
While NSLog is useful during the development stage, it is crucial to disable it before launching the app in production. Keeping NSLog active in the production version could expose logged information to potential attackers who might access the physical device or other applications on a jailbroken device.
Log files can be generated through various methods. The subsequent list outlines the options available on iOS:
- NSLog Method
- printf-like function
- NSAssert-like function
- Macro
Security risks from logging (NSLog and others)
Verbose logging often leaks sensitive runtime data, including tokens, request payloads, headers, and errors.
NSLog output persists in device logs and can be accessed via Xcode or third-party tools. On jailbroken devices, attackers can systematically harvest this information.
Keyboard cache
iOS offers a seamless and sophisticated keyboard experience, incorporating functionalities such as auto-correction, predictive text, and keyboard caching.
A range of options, including autocorrect and spell check, is provided to users to streamline keyboard input. These options are, by default, cached in .dat files in the “/private/var/mobile/Library/Keyboard/” folder and its associated subdirectories.
The implementation of these features, including passwords, credit card details, or personal data.
Risks from keyboard cache
The iOS keyboard learns and caches typed input to improve suggestions.
If not handled carefully, the implementation of keyboard caching may pose security vulnerabilities when managing sensitive information, including passwords, credit card numbers, or PII, which may be retained in the predictive text cache.
Attackers with device access can dump this cache and recover sensitive strings.
Summary table: Insecure storage risks in iOS
|
Storage mechanism |
Common mistake |
Real-world example |
Impact |
Secure practice |
|
NSUserDefaults |
Storing passwords or tokens in a plist |
Extractable via iTunes backup |
Account takeover |
Only store lightweight preferences |
|
Keychain |
Using AccessibleAlways |
Credentials are readable when locked |
Unauthorized access |
Use WhenUnlockedThisDeviceOnly |
|
SQLite / CoreData |
No encryption (default) |
PII extracted with forensic tools |
Identity theft, fraud |
Use SQLCipher or file-level encryption |
|
Realm |
Not enabling encryptionKey |
Plaintext Realm DB files |
Sensitive data exposure |
Configure encryption at initialization |
|
Couchbase Lite |
Default unencrypted files |
Offline caches fully exposed |
Data leaks & sync risks |
Enable Couchbase Lite’s encryption API |
|
Caching / Temp files |
Sensitive data in /tmp or screenshots |
Telegram cached deleted media |
Private data recovery |
Encrypt temp data, disable screen capture |
|
Logging (NSLog) |
Tokens or payloads logged |
Readable via Xcode or jailbreak tools |
Token hijack, replay attacks |
Disable verbose logging in production |
|
Keyboard Cache |
PII in predictive cache |
Passwords recovered from keyboard logs |
Credential leaks |
Disable autocorrect + secure text entry |
Expert opinion
.jpg?width=120&height=120&name=Abhinav%20VasisthWebinar%20(2).jpg)
![]()
Abhinav Vasisth, Appknox’s Security Research Lead, believes that
“Developers often underestimate local storage risks on iOS, assuming the sandbox is enough. But attackers exploit weak configurations, not just OS flaws.”
How to prevent insecure data storage in iOS apps?
Preventing insecure storage requires a defense-in-depth approach, combining secure APIs, strong encryption, and strict access controls.
Below are practical strategies, along with implementation snippets, that developers can apply immediately.
1. Use Keychain securely
Store credentials and tokens only in Keychain. Configure accessibility with kSecAttrAccessibleWhenUnlocked or a stricter setting, never Always.
Swift example
let account = “[email protected]”
let password = “SuperSecurePass!”.data(using: .utf8)!
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: password,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print(“Securely stored in Keychain”)
}
2. Encrypt all databases
SQLite with SQLCipher
PRAGMA key = ‘super_secret_key’;
Realm encryption setup
var config = Realm.Configuration()
let key = Data(count: 64)
_ = key.withUnsafeBytes { SecRandomCopyBytes(kSecRandomDefault, 64, $0.baseAddress!) }
config.encryptionKey = key
let realm = try! Realm(configuration: config)
Couchbase Lite encryption
let config = DatabaseConfiguration()
config.encryptionKey = EncryptionKey(password: “super_secret_key”)
let database = try Database(name: “secure-db”, config: config)
If required, encrypt before writing.
let sensitiveData = “PII-data”.data(using: .utf8)!
let encrypted = try AES.GCM.seal(sensitiveData, using: key).combined
try encrypted?.write(to: secureURL)
This prevents the app’s view from being captured in the app switcher.
Remove sensitive data from logs. For production builds:
textField.isSecureTextEntry = true
textField.autocorrectionType = .no
textField.spellCheckingType = .no
textField.smartInsertDeleteType = .no
Use CryptoKit instead of rolling custom crypto.
let key = SymmetricKey(size: .bits256)
let data = “Sensitive Info”.data(using: .utf8)!
let sealedBox = try! AES.GCM.seal(data, using: key)
Yet, forensic investigations consistently reveal apps leaking credentials, personal data, and tokens through insecure mechanisms.
Attackers no longer require jailbreaks or advanced exploits. Many insecure storage flaws can be exploited with basic tools.
Developers must treat local storage with the same rigor as network security: never assume the device is safe. Encryption, restricted APIs, and data minimization should be non-negotiable. Security teams must integrate static and dynamic analysis into the SDLC to catch unsafe storage practices before release.
In the current mobile threat landscape, secure storage is no longer optional; it has become a baseline expectation for any app handling user data.
NSUserDefaults saves values in a plaintext .plist file inside the app’s container. Anyone with access to the device filesystem or backup can extract this data. It should only be used for non-sensitive preferences (e.g., UI settings, feature flags).
Use the iOS Keychain with strict accessibility attributes such as kSecAttrAccessibleWhenUnlockedThisDeviceOnly. This ensures data is only available when the device is unlocked and cannot be migrated to other devices.
Mark sensitive views as secure by setting self.view.window?.isSecure = true. This prevents iOS from capturing those views when the app transitions to the background.













