Problem
In SDK 1.13.1, app developers have no way to force the local SQLCipher database to be encrypted. The encryptDB flag is only honored when it's set in the server's generalSettings endpoint, which many instance administrators don't enable.
Apps that hold sensitive offline data (patient records, PII) therefore ship with cleartext SQLite at /data/data/<pkg>/databases/ by default, recoverable via adb backup (pre-API-23 or vendor-rooted devices) or any filesystem access on a rooted device.
What's already in place
The SDK already has all the pieces — they just aren't reachable:
Everything above is internal — there is no public entry point.
Requested API
Either (preferred) or both:
A. D2Configuration.forceDatabaseEncryption(Boolean)
D2Configuration.builder()
.appName(...)
.forceDatabaseEncryption(true) // overrides server-side encryptDB
.build()
B. Overload on UserModule
fun blockingLogIn(
username: String,
password: String,
serverUrl: String,
forceEncryption: Boolean = false, // default = current behaviour
): User
Semantics: if the app sets this, LogInDatabaseManager.loadDatabaseOnline should use forceEncryption || generalSettingCall.isDatabaseEncrypted() instead of the server flag alone. Existing behaviour unchanged when the app doesn't opt in.
Why it matters
Without an app-facing switch, apps built on this SDK can't ship a secure-by-default offline store even when they want to. Security-conscious deployments (e.g. HIV/TB patient registries) are currently forced to either:
- require every server admin to enable
encryptDB — not realistic across dozens of instances, and
- ship cleartext databases.
References
- DHIS2 Android Capture App audit — S-A2 line 34
- Related internal:
RoomDatabaseManager.createOrOpenEncryptedDatabase(name, password) already exists and is wired end-to-end.
Problem
In SDK 1.13.1, app developers have no way to force the local SQLCipher database to be encrypted. The
encryptDBflag is only honored when it's set in the server'sgeneralSettingsendpoint, which many instance administrators don't enable.Apps that hold sensitive offline data (patient records, PII) therefore ship with cleartext SQLite at
/data/data/<pkg>/databases/by default, recoverable viaadb backup(pre-API-23 or vendor-rooted devices) or any filesystem access on a rooted device.What's already in place
The SDK already has all the pieces — they just aren't reachable:
DatabaseEncryptionPasswordManagerauto-generates and Keystore-stores the per-database password viaAndroidSecureStore.MultiUserDatabaseManager.loadExistingChangingEncryptionIfRequiredOtherwiseCreateNew(serverUrl, username, encrypted)already takes anencrypted: Booleanparam.LogInDatabaseManager.loadDatabaseOnlinehard-codes theisEncryptedsource togeneralSettingCall.isDatabaseEncrypted(), which returns the server-side flag.Everything above is
internal— there is no public entry point.Requested API
Either (preferred) or both:
A.
D2Configuration.forceDatabaseEncryption(Boolean)B. Overload on
UserModuleSemantics: if the app sets this,
LogInDatabaseManager.loadDatabaseOnlineshould useforceEncryption || generalSettingCall.isDatabaseEncrypted()instead of the server flag alone. Existing behaviour unchanged when the app doesn't opt in.Why it matters
Without an app-facing switch, apps built on this SDK can't ship a secure-by-default offline store even when they want to. Security-conscious deployments (e.g. HIV/TB patient registries) are currently forced to either:
encryptDB— not realistic across dozens of instances, andReferences
RoomDatabaseManager.createOrOpenEncryptedDatabase(name, password)already exists and is wired end-to-end.