-
Notifications
You must be signed in to change notification settings - Fork 926
[PM-30703] Introduce CXF payload parser and update to alpha04 #6347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Great job! No new security vulnerabilities introduced in this pull request |
cxf/src/main/kotlin/com/bitwarden/cxf/parser/CredentialExchangePayloadParserImpl.kt
Outdated
Show resolved
Hide resolved
037610f to
80720fb
Compare
|
Claude finished @SaintPatrck's task in 2m 29s —— View job Code Review SummaryThis PR introduces a well-structured CXF payload parser and updates to Critical Issues (Must Fix)❌ Silent Multi-Account Data Loss (CredentialExchangePayloadParserImpl.kt:104)
Important Issues (Should Fix)
Strengths✅ Excellent separation of concerns - Parser extraction from import manager follows SRP Architecture Compliance
Additional ObservationsBinary Addition: Breaking Changes: The Refactoring Impact: The test refactoring in VerdictRequires Changes - The architectural improvements are excellent, but the data loss and decoding issues must be fixed before merge. The Base64 decoding bug could cause production failures for certain payloads, and silent multi-account data loss is a user trust issue. Once the critical and important issues are addressed, this will be a solid improvement to the codebase. Generated by Claude Code - Bitwarden Code Review Agent |
| // We only support single account import, silently discard additional | ||
| // accounts. | ||
| val accountsJson = json.encodeToString( | ||
| value = exportResponse.accounts.first(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌ CRITICAL: Silent multi-account data loss
The comment on line 101-102 states "silently discard additional accounts," but this is a security and data integrity concern:
Issues:
- No user notification: Users have no way to know their additional accounts were dropped
- No logging: No Timber log to track when this occurs in production
- Documentation gap: The public
CredentialExchangePayloadParserinterface doesn't document this single-account limitation
Why this matters:
A user exporting multiple accounts from another password manager would see a successful import but silently lose all but the first account. This could lead to:
- Lost credentials they believe were imported
- Security incidents if they delete source data assuming import succeeded
- Support burden when users discover missing data
Required fixes:
- Add
Timber.w()logging whenaccounts.size > 1to track occurrence - Update
CredentialExchangePayloadParserKDoc to explicitly document single-account limitation - Consider returning a new
CredentialExchangePayloadvariant likePartialImport(accountsJson: String, droppedAccountCount: Int)to inform callers
cxf/src/main/kotlin/com/bitwarden/cxf/parser/CredentialExchangePayloadParserImpl.kt
Outdated
Show resolved
Hide resolved
| } else { | ||
| cipherList | ||
| } | ||
| .map { syncVault(it) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The uploadCiphers function converts specific ImportCiphersResponseJson.Invalid responses into a generic ImportCredentialsUnknownErrorException, losing valuable error context.
Problems:
- Lost validation errors:
Invalidcontains avalidationErrorsmap with specific field-level errors, but this is completely discarded - Debugging difficulty: Support and developers lose insight into why the import failed on the server side
- User experience: Generic errors provide no actionable feedback
Recommended fix:
is ImportCiphersResponseJson.Invalid -> {
// Log validation errors for debugging
Timber.w("Import ciphers validation failed: ${response.validationErrors}")
Result.failure(
ImportCredentialsUnknownErrorException(
"Server validation failed: ${response.validationErrors.keys.joinToString()}"
)
)
}Alternatively, consider creating a custom exception type that preserves the validation errors for upstream handling.
43e34e9 to
b5cb0dd
Compare
…d parser
This commit updates the Credential Exchange (CXF) implementation to align with the `androidx.credentials.providerevents:1.0.0-alpha04` library. The primary objective is to adapt to the breaking changes introduced in this version, which simplifies the API and removes the custom JSON request/response structure in favor of direct parameters.
A key part of this refactor is the introduction of a dedicated `CredentialExchangePayloadParser`. This parser is responsible for validating and processing the incoming JSON payload from the exporting credential manager.
Behavioral changes:
- The structure of the `ImportCredentialsRequest` sent to the credential provider has changed. It no longer uses a custom JSON string but instead passes `credentialTypes` and `knownExtensions` directly.
- The response from the credential provider is no longer a nested JSON structure with a Base64 encoded payload. It is now a direct JSON object representing the exported data.
Specific changes:
- **Dependencies**:
- Upgraded `androidx.credentials.providerevents` to `1.0.0-alpha04`.
- Added Hilt dependencies to the `cxf` module for dependency injection.
- **CXF Payload Parsing**:
- Created `CredentialExchangePayloadParser` interface and its `CredentialExchangePayloadParserImpl` implementation to handle the parsing of incoming CXF JSON data.
- Introduced a `CredentialExchangePayload` sealed class to represent the different outcomes of parsing: `Importable`, `NoItems`, and `Error`.
- Added a `CxfModule` to provide the parser implementation via Hilt.
- Added comprehensive unit tests for `CredentialExchangePayloadParserImpl` to cover valid payloads, version checks, invalid JSON, and error conditions.
- **Import Logic**:
- Refactored `CredentialExchangeImporterImpl` to use the new `ImportCredentialsRequest` constructor, passing `credentialTypes` and `knownExtensions` directly instead of building a JSON string.
- Updated `CredentialExchangeImportManagerImpl` to use the new `CredentialExchangePayloadParser`. The manager now delegates payload validation and parsing, simplifying its own logic to focus on the import, upload, and sync process.
- Removed the now-obsolete manual parsing of the two-layered CXP/CXF JSON structure and Base64 decoding.
- **Export Logic**:
- In `CredentialExchangeRegistryImpl`, added the `exportMatcher` WASM binary required by the `alpha04` API when registering an export flow.
- Simplified `CredentialExchangeCompletionManagerImpl` to directly return the export data as a JSON string, removing the previous logic that wrapped it in a `CXP` protocol message with Base64 encoding.
- **Testing**:
- Updated unit tests across `app` and `cxf` modules (`CredentialExchangeImporterTest`, `MainViewModelTest`, `CredentialExchangeImportManagerTest`, etc.) to reflect the API changes in `ImportCredentialsRequest` and the new parsing flow.
- Removed outdated test logic related to the old JSON structure and Base64 decoding.
b5cb0dd to
9de5ff0
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6347 +/- ##
==========================================
- Coverage 85.49% 85.49% -0.01%
==========================================
Files 764 765 +1
Lines 54724 54714 -10
Branches 7881 7881
==========================================
- Hits 46785 46775 -10
Misses 5201 5201
Partials 2738 2738 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|

🎟️ Tracking
PM-30703
📔 Objective
Update the Credential Exchange (CXF/CXP) implementation to align with the
androidx.credentials.providerevents:1.0.0-alpha04library. The previous implementation was based onalpha03and is now obsolete.The primary behavioral change is the removal of the two-layered JSON structure (CXP wrapping CXF). The
alpha04specification simplifies this to a single, direct JSON payload for credential exchange.Specific changes include:
Dependency Update:
androidx.credentials.providereventsfrom1.0.0-alpha03to1.0.0-alpha04.Payload Parsing:
CredentialExchangePayloadParserto handle the new direct JSON payload structure. This parser validates the CXF version, checks for the presence of accounts, and handles various error conditions.CredentialExchangeImportManageris refactored to use this new parser, removing the now-unnecessary logic for decoding the two-layered, base64-encoded payload.Import/Export Flow:
CredentialExchangeImporterImpl: Updated to use the modernImportCredentialsRequestbuilder, which no longer requires manual JSON construction.CredentialExchangeCompletionManagerImpl: Modified to return the new, simplified direct JSON response, removing the CXP wrapper and base64 encoding.CredentialExchangeRegistryImpl: Aligned withalpha04by including a defaultexport_matcher.bin(a WASM binary from Google) in the registration request.DI and Module Structure:
CxfModuleto provide theCredentialExchangePayloadParser.build.gradle.ktsfor thecxfmodule to include Hilt dependencies for DI.Testing:
CredentialExchangePayloadParserto cover valid payloads, version checks, and various error states.CredentialExchangeImporterTestandCredentialExchangeImportManagerTestto reflect the API and structural changes from the library update.⏰ Reminders before review
🦮 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