Mitigation Strategy: Encryption at Rest (Realm Encryption)
-
Description:
- Key Generation: Generate a 64-byte (512-bit) cryptographically secure random key. Do not use a password directly; use a key derivation function (KDF) if deriving the key from a password.
- Secure Key Storage: (This part is external to Realm, but crucial. I'm including it for completeness, but it's not a Realm API.) Use platform-specific secure storage (Android Keystore, iOS Keychain, etc.).
- Realm Configuration: Pass the key to the
RealmConfiguration
when opening the Realm using the.encryptionKey()
method:val config = RealmConfiguration.Builder(schema = setOf(MyRealmObject::class)) .encryptionKey(realmKey) // realmKey from secure storage .build() val realm = Realm.open(config)
- Key Rotation: Use Realm's
Realm.writeCopyTo()
to re-encrypt the Realm with a new key. This is a Realm-specific API call. You provide the new configuration (with the new key) to this method.// Assuming you have a 'newRealmKey' and 'oldRealm' val newConfig = RealmConfiguration.Builder(schema = setOf(MyRealmObject::class)) .encryptionKey(newRealmKey) .build() oldRealm.writeCopyTo(newConfig) // Re-encrypts the data
- User-Based Keys (if applicable): If you have multiple users, derive a unique key per user. The key derivation is external to Realm, but you'd use the resulting key with
.encryptionKey()
as above.
-
Threats Mitigated:
- Data Breach from Device Compromise (Severity: Critical): Protects against unauthorized access to the Realm database file.
- Data Tampering (Severity: High): Encryption (with authenticated encryption) provides integrity checks.
- Reverse Engineering (Severity: Medium): Makes data extraction harder.
-
Impact:
- Data Breach from Device Compromise: Risk reduced from Critical to Low.
- Data Tampering: Risk reduced from High to Low.
- Reverse Engineering: Risk reduced from Medium to Low.
-
Currently Implemented: [FILL IN: e.g., "Implemented using Android Keystore.
writeCopyTo
used for key rotation."] -
Missing Implementation: [FILL IN: e.g., "User-based keys are not used, even though the application supports multiple users."]
Mitigation Strategy: Fine-Grained Access Control (Realm Query-Based Permissions - Realm Sync Only)
-
Description:
- Identify Roles and Permissions: Define roles and the permissions each role should have.
- Implement Permission Rules: Use Realm's query-based permissions system (configured in the Realm Cloud UI or via the Admin API). These rules are written in a JavaScript-like syntax. This is entirely within the Realm ecosystem.
// Example (in the Realm Cloud UI) { "roles": ["user"], "rules": { "MyObject": { "read": "owner == '%user.id'", "write": "owner == '%user.id'" } } }
- Assign Roles to Users: (This is often done outside of Realm's direct APIs, in your application's user management, but it affects how Realm permissions work.)
- Test Permissions: Thoroughly test your permission rules. This testing often involves interacting with the Realm SDK to simulate different users.
- Regular Audits: Periodically review your permission rules (within the Realm Cloud UI or via the Admin API).
-
Threats Mitigated:
- Unauthorized Data Access (Severity: Critical): Prevents unauthorized access via Realm Sync.
- Unauthorized Data Modification (Severity: High): Prevents unauthorized modification via Realm Sync.
- Privilege Escalation (Severity: High): Limits the impact of compromised accounts.
-
Impact:
- Unauthorized Data Access: Risk reduced from Critical to Low.
- Unauthorized Data Modification: Risk reduced from High to Low.
- Privilege Escalation: Risk reduced from High to Low.
-
Currently Implemented: [FILL IN: e.g., "Basic permission rules implemented. Rules allow users to read/write their own data."]
-
Missing Implementation: [FILL IN: e.g., "No automated testing of permission rules within the CI/CD pipeline."]
Mitigation Strategy: Data Validation (Schema Enforcement)
-
Description:
- Realm Schema Definition: Define your Realm object model using Realm's schema definition features. This is fundamental to how Realm works.
- Use specific data types (
Int
,String
,Boolean
,Date
,RealmList
,RealmSet
, etc.). - Use
@Required
for non-nullable fields. - Use
@PrimaryKey
for unique identifiers. - Use
@Index
to improve query performance (and, indirectly, security by making brute-force attempts slower).
open class MyObject : RealmObject { @PrimaryKey var id: Int = 0 @Required var name: String = "" var age: Int? = null // Optional @Index var email: String = "" }
- Use specific data types (
- Input Validation (Before Writing to Realm): While additional validation is recommended (and often done outside of Realm's direct APIs), Realm's schema enforces the basic types and
@Required
constraints. This is a direct Realm mitigation.
- Realm Schema Definition: Define your Realm object model using Realm's schema definition features. This is fundamental to how Realm works.
-
Threats Mitigated:
- Data Corruption (Severity: Medium): Prevents invalid data types from being stored.
- Logic Errors (Severity: Low): Enforces basic data integrity constraints.
-
Impact:
- Data Corruption: Risk reduced from Medium to Low.
- Logic Errors: Risk reduced from Low to Very Low.
-
Currently Implemented: [FILL IN: e.g., "Realm schema defined with data types,
@Required
, and@PrimaryKey
."] -
Missing Implementation: [FILL IN: e.g., "No
@Index
annotations used on frequently queried fields."]
Mitigation Strategy: Secure Object Deletion (Basic Deletion)
-
Description:
- Standard Deletion: Use
Realm.delete()
orRealm.deleteFromRealm()
(or the newerdelete()
within awrite
block) to remove objects from the Realm. This is the core Realm deletion API.realm.write { val myObject = query<MyObject>("id == $0", objectId).first().find() myObject?.let { delete(it) } }
- Shredding: While the shredding logic itself is not part of the Realm API, the fact that you are modifying the Realm object before calling Realm's
delete()
makes this relevant. You are using Realm's write transaction to perform the shredding.
- Standard Deletion: Use
-
Threats Mitigated:
- Data Recovery After Deletion (Severity: Low to Medium): Reduces the chance of simple data recovery.
-
Impact:
- Data Recovery After Deletion: Risk reduced from Low/Medium to Low (without shredding) or Very Low (with shredding).
-
Currently Implemented: [FILL IN: e.g., "Standard
delete()
used withinwrite
blocks."] -
Missing Implementation: [FILL IN: e.g., "Shredding not implemented."]
Mitigation Strategy: Threading Considerations (Realm's Threading Model)
-
Description:
- Thread Confinement: Use
Realm.open()
(orRealm.getInstance()
) on each thread that needs to access the database. This is a fundamental requirement of Realm's threading model. - Transactions: Use
Realm.write
(or the olderRealm.executeTransaction
) to ensure write operations are atomic. This is a core Realm API for safe writes. - Refreshing: Use
Realm.refresh()
to update a Realm instance with changes from other threads. This is a Realm-provided method. - Kotlin Coroutines: Use Realm's
asFlow()
and suspend functions for asynchronous database operations. These are Realm-provided extensions for coroutine integration. - Object Passing: Avoid passing live Realm objects between threads. Use detached copies (obtained via
Realm.copyFromRealm()
, a Realm API) or pass primary keys and re-fetch the object on the other thread.
- Thread Confinement: Use
-
Threats Mitigated:
- Application Crashes (Severity: High): Prevents crashes from incorrect thread access.
- Data Corruption (Severity: High): Prevents data corruption from unsynchronized concurrent access.
-
Impact:
- Application Crashes: Risk reduced from High to Very Low.
- Data Corruption: Risk reduced from High to Very Low.
-
Currently Implemented: [FILL IN: e.g., "Kotlin Coroutines and
asFlow()
used.Realm.write
used for transactions."] -
Missing Implementation: [FILL IN: e.g., "
copyFromRealm()
not consistently used when passing data between coroutines."]