Skip to content

Conversation

@andrebispo5
Copy link
Contributor

@andrebispo5 andrebispo5 commented Sep 29, 2025

Note

Depends on PR: #5944

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-23278
https://bitwarden.atlassian.net/browse/PM-23577

📔 Objective

This pull request introduces functionality to ensure user KDF (Key Derivation Function) settings meet minimum security requirements. It adds logic to check if an account's KDF configuration is outdated and, if so, updates it automatically after password unlock, provided the relevant feature flag is enabled. The changes also include necessary model, service, and dependency updates to support this workflow.

KDF Minimums Enforcement and Update Workflow

  • Added new methods to AuthRepository and AuthRepositoryImpl to check if a user's KDF settings are below the minimum and to update them if needed, including integration with a feature flag (ForceUpdateKdfSettings). [1] [2]
  • Automatically triggers KDF update after password unlock if the user's settings are outdated and the feature flag is enabled.

Model and SDK Support

  • Introduced UpdateKdfMinimumsResult sealed class to model the result of updating KDF settings.
  • Added makeUpdateKdf method to VaultSdkSource and its implementation to generate updated KDF data using the SDK. [1] [2]
  • Added extension function toKdfRequestModel to convert SDK KDF objects to network request models.

Dependency Injection and Feature Flag Integration

  • Updated DI module (AuthRepositoryModule) to provide FeatureFlagManager to AuthRepositoryImpl. [1] [2] [3]

📸 Screenshots

Screen.Recording.2025-10-02.at.09.24.01.mov

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

# Conflicts:
#	app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt
#	app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/debugmenu/components/FeatureFlagListItems.kt
#	app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt
#	app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/handlers/VaultHandlers.kt
#	app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt
#	core/src/main/kotlin/com/bitwarden/core/data/manager/model/FlagKey.kt
#	network/src/main/kotlin/com/bitwarden/network/service/AccountsService.kt
#	network/src/main/kotlin/com/bitwarden/network/service/AccountsServiceImpl.kt
#	network/src/test/kotlin/com/bitwarden/network/service/AccountsServiceTest.kt
#	ui/src/main/res/values/strings.xml
…minimum

# Conflicts:
#	app/src/main/kotlin/com/x8bit/bitwarden/data/auth/repository/util/UserStateJsonExtensions.kt
#	core/src/main/kotlin/com/bitwarden/core/data/manager/model/FlagKey.kt
@github-actions
Copy link
Contributor

github-actions bot commented Sep 29, 2025

Logo
Checkmarx One – Scan Summary & Details521a5494-cb5a-41c4-a00a-8337bd69207c

New Issues (2)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt: 3050
detailsThe application uses the hard-coded password "mock_password" for authentication purposes, either using it to verify users' identities, or to acce...
ID: n7npCwWTHuohDSgD5OTttlWiV6Q%3D
Attack Vector
MEDIUM Use_of_Hardcoded_Password /app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt: 816
detailsThe application uses the hard-coded password "test_password" for authentication purposes, either using it to verify users' identities, or to acce...
ID: hF9bsk8oPhG6%2F0nqhQxopbQP1D4%3D
Attack Vector

@andrebispo5 andrebispo5 changed the base branch from main to pm-23280/kdf_changes_logout October 1, 2025 09:27
.updateKdfToMinimumsIfNeeded(password = password)
.also { result ->
if (result is UpdateKdfMinimumsResult.Error) {
Timber.e("Failed to silent update KDF settings: ${result.error}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we just do Timber.e(result.error, "Failed to silently update KDF settings.")?

)
.also { result ->
if (result is UpdateKdfMinimumsResult.Error) {
Timber.e("Failed to silent update KDF settings: ${result.error}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we do

Timber.e(result.error, "Failed to silently update KDF settings.")

* @param onDismissRequest called when the user attempts to dismiss the dialog (for example by
* tapping outside of it).
*/
@Suppress("LongMethod")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you double check if this is needed? I removed it and detekt didn't complain. 🤔

.asText(),
error = result.error,
)
Timber.e(message = "Failed to update kdf to minimums: ${result.error}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Another place we can pass the error as an arg instead.

Timber.e(result.error, "Failed to update kdf to minimums.")

🤔 Is this actually needed since we're logging errors in the data layer?

Comment on lines 1139 to 1140
<string name="kdf_update_failed_active_account_not_found">"Kdf update failed, active account not found. Please try again or contact us."</string>
<string name="an_error_occurred_while_trying_to_update_your_kdf_settings">"An error occurred while trying to update your kdf settings. Please try again or contact us."</string>
Copy link
Contributor

Choose a reason for hiding this comment

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

Should these be surrounded by quotes? If so, we should be using the and chars for opening and closing quotes.

Copy link
Collaborator

@david-livefront david-livefront Oct 8, 2025

Choose a reason for hiding this comment

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

Outer quotes like this do not actually appear in the displayed string, I actually just removed a bunch of these. I think they should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nice catch!

Copy link
Contributor

@SaintPatrck SaintPatrck left a comment

Choose a reason for hiding this comment

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

Left a few minor comments. Overall, it's looking good. Great job!

kdf = Kdf.Pbkdf2(iterations = DEFAULT_PBKDF2_ITERATIONS.toUInt()),
)
.fold(
onSuccess = { updateKdfOnServer(createUpdateKdfRequest(it)) },
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Comment on lines 95 to 106
private suspend fun updateKdfOnServer(request: UpdateKdfJsonRequest): UpdateKdfMinimumsResult {
return accountsService
.updateKdf(body = request)
.fold(
onSuccess = {
authDiskSource.userState = authDiskSource.userState
?.toUserStateJsonKdfUpdatedMinimums()
UpdateKdfMinimumsResult.Success
},
onFailure = { UpdateKdfMinimumsResult.Error(error = it) },
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I like that request creation is extracted, but I think this introduces an unnecessary fold operation. vaultSdkSource.makeUpdateKdf().flatMap will handle mapping a successful result to the result of accountsService.updateKdf(), then you only have to handle failures once, in the final fold().

return vaultSdkSource
    .makeUpdateKdf()
    .flatMap { response ->
        accountsService.updateKdf(
            request = createUpdateKdfRequest(response)
        )
    }
    .fold(
        onSuccess = { 
            authDiskSource.userState = authDiskSource.userState
                ?.toUserStateJsonKdfUpdatedMinimums()
            UpdateKdfMinimumsResult.Success
        },
        onFailure = { UpdateKdsMinimumsResult.Error(error = it) },
    )

SaintPatrck
SaintPatrck previously approved these changes Oct 8, 2025
Copy link
Contributor

@SaintPatrck SaintPatrck left a comment

Choose a reason for hiding this comment

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

Awesome! Thanks for that. LGTM

david-livefront
david-livefront previously approved these changes Oct 8, 2025
# Conflicts:
#	app/src/main/kotlin/com/x8bit/bitwarden/data/auth/manager/di/AuthManagerModule.kt
#	app/src/main/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModel.kt
#	app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt
david-livefront
david-livefront previously approved these changes Oct 8, 2025
@andrebispo5 andrebispo5 added this pull request to the merge queue Oct 9, 2025
Merged via the queue into main with commit d98ff64 Oct 9, 2025
9 checks passed
@andrebispo5 andrebispo5 deleted the pm-23278/kdf-upgrade-minimum branch October 9, 2025 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants