Repository navigation
[PM-44810] fix: Ignore "Vault Items" send type parsing [bug-factory poc] #7488
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| package com.x8bit.bitwarden.data.auth.repository.model | ||
|
|
||
| import com.bitwarden.core.data.serializer.SafeListSerializer | ||
| import com.bitwarden.network.model.SendAccessTypeJson | ||
| import com.bitwarden.network.model.SendTypeJson | ||
| import com.bitwarden.network.model.SyncResponseJson | ||
|
|
@@ -128,7 +129,8 @@ sealed class PolicyInformation { | |
| * when [whoCanAccess] is [SendAccessTypeJson.SPECIFIC_PEOPLE]. | ||
| * @property deletionHours The number of hours until a Send is deleted, if enforced. | ||
| * @property allowedSendTypes The types of Sends that are allowed to be created, if | ||
| * restricted. | ||
| * restricted. Send types unknown to this client are dropped rather than failing the decode of | ||
| * the whole policy. | ||
| */ | ||
| @Serializable | ||
| data class SendControls( | ||
|
|
@@ -147,6 +149,7 @@ sealed class PolicyInformation { | |
| @SerialName("deletionHours") | ||
| val deletionHours: Int?, | ||
|
|
||
| @Serializable(with = SafeListSerializer::class) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right β withdrawing my earlier finding@andrebispo5 I re-read both consumers and the behaviour matches what you describe. No code changes made. Create side β View side β my review claimed every existing Send would be marked That leaves no behavioural gap in this PR. The rest is genuinely PM-41095 β once One thing worth confirming on your side, since it is server-side knowledge I cannot verify from this repo: that "at least one type enabled" is enforced at policy-save time, so a client can never receive a policy whose entire allowlist consists of types it does not know. If that invariant ever loosens, the empty-list-to-unrestricted path becomes a real fail-open. Not a blocker here either way. No blocking findings from me on this change. Note: my original comment could not be edited β the comment-update tool returned
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this can just be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let me try, but I believe it will discard the other policy options.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup tested and it does not work it will make it all null. |
||
| @SerialName("allowedSendTypes") | ||
| val allowedSendTypes: List<SendTypeJson>?, | ||
|
Comment on lines
+152
to
154
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| ) : PolicyInformation() | ||
|
|
||
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.
allowedSendTypes = emptyList(), and the create flow treats that list as "no restriction".Details and fix
This PR makes
[2]decode toemptyList(), and the new test asserts exactly that. The consumers then disagree about what an empty list means:SendViewModel.singleAllowedSendTypeusesallowedSendTypes?.singleOrNull(), which givesnullfor an empty list. SohandleAddSendClickshows the full type picker and the user can start a Text or File Send, both of which the policy forbids.ViewSendViewModel.isSendTypeAllowedusesallowedSendTypes?.any { ... } ?: true, which givesfalsefor an empty list. So every existing Send is shown asTypeNotAllowed.The result: the list screen says existing Text and File Sends are not allowed, while the add button still lets the user create new ones. This is no worse than the base branch, where the whole policy was dropped. But the empty-list state is new, and nothing handles it.
Suggested fix: handle the empty list explicitly. One option is to resolve it in
PolicyManagerImpl.resolveEffectiveSendPolicy(for example, treat an emptyallowedSendTypesasdisableSend = trueuntil PM-41095 adds Item support). Another is to haveSendViewModelblock creation when the list is non-null and empty. Add a test that covers whichever you choose.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.
@claude This will be handled by another ticket, we just need to make sure that when a restriction is applied it is not being ignored.
Uh oh!
There was an error while loading. Please reload this page.
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.
Claude finished @andrebispo5's task in 1m 28s ββ View job
Confirmed β restrictions are enforced, and this PR is what stops them being ignored
allowedSendTypesfrom decode βPolicyManagerImplβSendViewModel/AddEditSendViewModel/ViewSendViewModel@andrebispo5 Agreed, and the code backs you up β the "restriction being ignored" case is exactly what this PR fixes, and it is wider than just the type list.
Why the ignore is wider than
allowedSendTypesPolicy.policyInformationdecodes the whole blob withdecodeFromStringOrNull(SyncResponseJsonExtensions.kt:157), so one unknown enum value returnsnullfor the entireSendControlsobject.PolicyManagerImpl.resolveEffectiveSendPolicythen drops it inmapNotNull(PolicyManagerImpl.kt:166-169), and that org never entersorganizationIdsWithSendControls(line 171). Every field of that policy is lost β not just the type list, butdisableSend,disableHideEmail,deletionHours,whoCanAccessandallowedDomainstoo.So on
main, an admin who ticks "Vault Items" alongside Text gets a policy where evendisableSendis silently ignored on Android. That is the real fail-open, and this PR closes it.Enforcement matrix
allowedSendTypesfrom servermainnull[0],[1],[0,1][0,2](Text + Vault Items)disableSend,deletionHours,whoCanAccess,disableHideEmail,allowedDomainsand the type restriction all ignored[TEXT];singleAllowedSendTyperesolves to Text, so the picker is skipped and only a Text Send can be created (SendViewModel.kt:335-343, 940-943), types filter hidden (line 535), and every other field is enforced[2]onlyemptyList()and stays permissive β PM-41095The
[0,2]row is the one an admin actually produces when they allow Text plus Vault Items, and it goes from "nothing enforced" to "fully enforced, Text only". No restriction that this client can express is ignored after the change.The one residual case, and why it is correctly deferred
[2]-only decodes toemptyList(), andsingleOrNull()on an empty list isnull, so the type dimension reads as unrestricted. Two things make that the right call for this PR:mainβdisableSend,deletionHours,whoCanAccess,disableHideEmailandallowedDomainsfrom that same policy now apply, where before they were thrown away with it.SendTypeJson.ITEMexists. The Item-typeTODObranches would throw, andSendItemTypehas no Item value β which is PM-41095, as you say.Worth confirming server-side (not verifiable from this repo): that the policy editor enforces at least one type selected, so a
[2]-only policy is not something a client can receive in the first place. If that holds, the residual row is unreachable today.The view side is unaffected either way:
policyRestrictionis gated onisSendDisabled, which comes fromsendView.disabledset by the server (ViewSendViewModel.kt:272, 331-340), not derived from the allowlist.No blocking findings. No code changes made.
Note: I could not run Gradle in this job (the test command was not in the allowed tool list), so the verification above is from reading the code plus the test run already recorded in the PR description.
Β· Branch
PM-44810-send-controls-vault-items