[PM-19108] Fix untrusted privileged app origin validation error handling (#5432)

This commit is contained in:
Patrick Honkonen 2025-06-27 11:53:19 -04:00 committed by GitHub
parent bbdf8552c9
commit 288efb3611
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 7 deletions

View File

@ -94,7 +94,6 @@ import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toSendItemType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toVaultItemCipherType
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.toViewState
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.updateWithAdditionalDataIfNecessary
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultAction
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
@ -116,7 +115,6 @@ import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.time.Clock
import javax.inject.Inject
import kotlin.collections.map
/**
* Manages [VaultItemListingState], handles [VaultItemListingsAction],
@ -1985,11 +1983,11 @@ class VaultItemListingViewModel @Inject constructor(
) {
mutableStateFlow.update {
it.copy(
dialogState = when (error) {
is ValidateOriginResult.Error.PrivilegedAppNotAllowed -> {
@Suppress("MaxLineLength")
dialogState = when {
shouldShowTrustPrompt(error) -> {
VaultItemListingState.DialogState.TrustPrivilegedAddPrompt(
message = R.string.passkey_operation_failed_because_browser_x_is_not_trusted
message = R.string
.passkey_operation_failed_because_browser_x_is_not_trusted
.asText(callingAppInfo.packageName),
selectedCipherId = selectedCipherId,
)
@ -2006,6 +2004,10 @@ class VaultItemListingViewModel @Inject constructor(
}
}
private fun shouldShowTrustPrompt(error: ValidateOriginResult.Error): Boolean =
error is ValidateOriginResult.Error.PrivilegedAppNotAllowed &&
featureFlagManager.getFeatureFlag(FlagKey.UserManagedPrivilegedApps)
private fun handleFido2AssertionDataReceive(
action: VaultItemListingsAction.Internal.Fido2AssertionDataReceive,
) {

View File

@ -245,6 +245,9 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
every {
getFeatureFlagFlow(FlagKey.RemoveCardPolicy)
} returns mutableRemoveCardPolicyFeatureFlow
every {
getFeatureFlag(FlagKey.UserManagedPrivilegedApps)
} returns true
}
private val initialState = createVaultItemListingState()
@ -2868,7 +2871,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `ValidateOriginResult should update dialog state on PrivilegedAppNotAllowed error`() =
fun `ValidateOriginResult should show TrustPrivilegedAddPrompt dialog when feature flag is on`() =
runTest {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
@ -2893,6 +2896,36 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `ValidateOriginResult should show not show TrustPrivilegedAppPrompt dialog when feature flag is off`() =
runTest {
specialCircumstanceManager.specialCircumstance =
SpecialCircumstance.ProviderCreateCredential(
createCredentialRequest = createMockCreateCredentialRequest(number = 1),
)
coEvery {
originManager.validateOrigin(
relyingPartyId = DEFAULT_RELYING_PARTY_ID,
callingAppInfo = mockCallingAppInfo,
)
} returns ValidateOriginResult.Error.PrivilegedAppNotAllowed
every {
featureFlagManager.getFeatureFlag(FlagKey.UserManagedPrivilegedApps)
} returns false
val viewModel = createVaultItemListingViewModel()
assertEquals(
VaultItemListingState.DialogState.CredentialManagerOperationFail(
title = R.string.an_error_has_occurred.asText(),
message = R.string.passkey_operation_failed_because_browser_is_not_privileged
.asText(),
),
viewModel.stateFlow.value.dialogState,
)
}
@Suppress("MaxLineLength")
@Test
fun `ValidateOriginResult should update dialog state on PrivilegedAppSignatureNotFound error`() =