Skip to content

Conversation

@alperozturk96
Copy link
Collaborator

@alperozturk96 alperozturk96 commented Jan 23, 2026

  • Tests written, or not not needed

Issue

The introduction of E2EE v2.1 exposed multiple code paths that relied on exact version matching (== 2.0), causing logic meant for v2.x to be skipped. As a result, the app crashes when interacting with encrypted folders created using E2EE 2.1.

How to reproduce

  1. Install End-to-End Encrypted app v2.0.0-rc.6.
  2. Create an encrypted folder
  3. Refresh the newly created folder
  4. App crashes; the folder remains locked and uploads are blocked

Changes

  • Treats E2EE v2.1 as compatible with v2.0 logic (v2 or above)
  • Replaces exact version checks with consolidated helpers to avoid missing logic for future versions
  • Deduplicates repeated E2EE version checks and centralizes them in a single helper
  • Adds extension helpers (e.g. resolving E2EE version from capabilities) to reduce code duplication
  • Adds unit tests for the new version helper to prevent regressions

Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
@alperozturk96
Copy link
Collaborator Author

/backport to stable-3.35


if (E2EVersionHelper.INSTANCE.isV2orAbove(version)) {
EncryptionUtilsV2 encryptionUtilsV2 = new EncryptionUtilsV2();
return encryptionUtilsV2.parseAnyMetadata(getMetadataOperationResult.getResultData(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encryptionUtilsV2.parseAnyMetadata needs to be used for v2.1 and v2.0.

RemoteOperationResult<String> uploadMetadataOperationResult;
if (metadataExists) {
// update metadata
if (version == E2EVersion.V2_0) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact version checks break the app and require manual updates for every new version. This logic has been replaced with E2EVersionHelper.

object : TypeToken<EncryptedFolderMetadataFile>() {}
)

val decryptedFolderMetadata = if (v2.version == "2.0" || v2.version == "2") {
Copy link
Collaborator Author

@alperozturk96 alperozturk96 Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v2.version == "2.0" || v2.version == "2" Fragile and dangerous check and it will not work with 2.1 replaced with E2EVersionHelper.fromVersionString

Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
* Supports both V1 and V2 metadata formats and falls back safely
* to [E2EVersion.UNKNOWN] if parsing fails.
*/
fun fromMetadata(metadata: String): E2EVersion = runCatching {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacement of public static E2EVersion determinateVersion(String metadata) {

Tries v1 if fails v2 if fails E2EVersion.UNKNOWN

@Transient
val filedrop: MutableMap<String, DecryptedFile> = HashMap(),
val version: String = "2.0"
val version: String = E2EVersionHelper.latestVersion(true).value
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaces hardcoded hidden strings with actual latest version so that in future we dont come across issues like this. @tobiasKaminsky

localFilesMap = prefillLocalFilesMap(metadataFileV1, fileDataStorageManager.getFolderContent(mLocalFolder, false));
} else {
e2EVersion = E2EVersion.V2_0;
e2EVersion = E2EVersionHelper.INSTANCE.latestVersion(true);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, for each version iteration, these hidden hardcoded values need to be upgraded. With latestVersion function we can just replace from there. In this case, E2EVersion.V2_1 should be the new value.

@github-actions
Copy link

blue-Light-Screenshot test failed, but no output was generated. Maybe a preliminary stage failed.

@github-actions
Copy link

Codacy

SpotBugs

CategoryBaseNew
Bad practice4343
Correctness7474
Dodgy code256253
Experimental11
Internationalization77
Malicious code vulnerability33
Multithreaded correctness3434
Performance4343
Security1818
Total479476

@github-actions
Copy link

APK file: https://www.kaminsky.me/nc-dev/android-artifacts/16345.apk

qrcode

To test this change/fix you can simply download above APK file and install and test it in parallel to your existing Nextcloud app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants