-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[PM-25675] - fix NormalCipherPermissions.CanDelete #6666
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
|
Claude finished @jaasen-livefront's task —— View job Code Review CompleteTasks
SummaryThis PR fixes a critical bug in FindingsFinding 1: Test change may not accurately reflect production behavior (test/Core.Test/Vault/Authorization/Permissions/NormalCipherPermissionTests.cs:95) 💭 The Context and implicationsAccording to the PR description and SQL view analysis:
The updated test now uses Question: Was this change intentional to match the SQL view behavior? Or should the test maintain Finding 2: Incomplete fix -
Recommendation: Review whether Finding 3: PR description quality 💭 The PR description is well-structured and includes:
The description effectively explains the root cause (SQL view behavior) and the solution (adding OrganizationId check). Good Practices Observed
Security Analysis✅ No security concerns identified. The fix correctly enforces ownership boundaries between personal and organization ciphers, which is critical for maintaining zero-knowledge architecture. By checking Action Items
|
|
Great job! No new security vulnerabilities introduced in this pull request |
| var user = new User { Id = Guid.Empty }; | ||
| var organizationId = Guid.NewGuid(); | ||
| var cipherDetails = new CipherDetails { Manage = manage, Edit = edit, UserId = null, OrganizationId = organizationId }; | ||
| var cipherDetails = new CipherDetails { Manage = manage, Edit = edit, UserId = user.Id, OrganizationId = organizationId }; |
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.
💭 This test now sets UserId = user.Id for organization ciphers, which matches what the SQL view (UserCipherDetails) returns to the application layer. However, this differs from the actual database state where org ciphers have UserId = null.
Question: Is this intentional to match the SQL view behavior? Or should the test maintain UserId = null to better represent the underlying data model?
For comparison, the CanRestore_WhenCipherIsOwnedByOrganization test (line 23) still uses UserId = null. Should that be updated for consistency, or is there a reason for the difference?
| } | ||
|
|
||
| if (user.Id == cipherDetails.UserId) | ||
| if (cipherDetails.OrganizationId == null && user.Id == cipherDetails.UserId) |
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.
👍 Excellent fix! Adding the cipherDetails.OrganizationId == null check correctly distinguishes between personal and organization ciphers, even when the SQL view injects the user's ID into UserId for org ciphers.
This properly enforces the ownership boundary: personal ciphers can be deleted by their owner (UserId matches and no OrganizationId), while org ciphers must go through the organization permission checks below.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6666 +/- ##
==========================================
+ Coverage 53.10% 53.41% +0.31%
==========================================
Files 1903 1910 +7
Lines 84877 85156 +279
Branches 7633 7651 +18
==========================================
+ Hits 45071 45484 +413
+ Misses 38055 37913 -142
- Partials 1751 1759 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|

🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-25675
📔 Objective
When fetching organization-owned ciphers, the SQL view (UserCipherDetails) injects the current user’s Id into cipherDetails.UserId even when the cipher’s true UserId in the DB is null.
This caused NormalCipherPermissions to treat org ciphers as personal items, because the old logic only checked for matching user.Id and cipher.UserId. Adding a check for cipher.OrganizationId fixed the issue. Updating a couple tests to test the correct method and be a bit sturdier should help avoid regressions.
📸 Screenshots
Screen.Recording.2025-12-01.at.4.32.15.PM.mov
⏰ 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