Skip to content

Conversation

@jaasen-livefront
Copy link
Collaborator

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-29017

📔 Objective

This PR fixes an issue where the server would return a 400 if a user without hidden pw permission attempted to save a cipher that didn't currently have a key.

Some tests were updated and to more accurately test the new logic.

Note

This presumes a user without hidden pw permission should still be able to update non password fields even if the key is absent from the cipher for some reason.

📸 Screenshots

⏰ 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

@jaasen-livefront jaasen-livefront requested a review from a team as a code owner December 13, 2025 01:38
@jaasen-livefront jaasen-livefront changed the title [PM-29017] - improve logic for cipher SaveDetailsAsync validation. fix tests [PM-29017] - improve logic for cipher SaveDetailsAsync validation Dec 13, 2025
@claude
Copy link
Contributor

claude bot commented Dec 13, 2025

Claude finished @jaasen-livefront's task in 1m 50s —— View job


PR Review Complete ✓

I've reviewed the changes in this PR that improve the cipher SaveDetailsAsync validation logic.


Summary

This PR fixes an issue where users without hidden password permission would receive a 400 error when attempting to save a cipher that didn't have a key. The fix changes the validation logic from rejecting the operation to silently preserving the existing key value.

Issues Found

🔴 Critical: Test Logic Error

File: test/Core.Test/Vault/Services/CipherServiceTests.cs:1371

The test SaveDetailsAsync_CipherKeyNotChangedWithoutPermission has incorrect test setup. On line 1371, it passes permission: true when the test name and intent clearly indicate it should be testing the case without permission (permission: false).

var deps = GetSaveDetailsAsyncDependencies(
    sutProvider,
    newPassword: "NewPassword",
    permission: true,  // ❌ Should be false
    key: "NewKey"
);

This means the test is not actually validating the behavior described by PM-29017. The test currently verifies that when a user has permission and provides a new key, the key gets reset to the original - which doesn't match the scenario being fixed.

Expected: The test should use permission: false to verify that users without ViewPassword permission cannot change the key even if they provide one.


📝 Minor: Code Style Issue

File: src/Core/Vault/Services/Implementations/CipherService.cs:1033

Double semicolon on line 1033:

cipher.Key = existingCipher.Key; ;  // Extra semicolon

Should be:

cipher.Key = existingCipher.Key;

📝 Minor: Typo in Comment

File: src/Core/Vault/Services/Implementations/CipherService.cs:1034

Line 1034 has a typo: "fileds" should be "fields"

// Keep only non-hidden fileds from the new cipher

Recommendations

  1. Fix the test on line 1371 - This is the most critical issue as it means the core scenario isn't properly tested
  2. Remove the extra semicolon on line 1033
  3. Fix the typo on line 1034

Security Assessment

✅ The approach of silently preserving existing values for hidden-password users is appropriate and maintains zero-knowledge security principles. The change is less disruptive than throwing an error and still prevents unauthorized modifications.


Review Summary

  • 1 critical issue (incorrect test logic)
  • 📝 2 minor issues (code style & typo)
  • ✅ Security approach is sound

throw new BadRequestException("You do not have permission to add cipher key encryption.");
}
// For hidden-password users, never allow Key to change at all.
cipher.Key = existingCipher.Key; ;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Code style: Double semicolon here - should be single semicolon.

}
// For hidden-password users, never allow Key to change at all.
cipher.Key = existingCipher.Key; ;
// Keep only non-hidden fileds from the new cipher
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 Typo: "fileds" should be "fields"

var deps = GetSaveDetailsAsyncDependencies(
sutProvider,
newPassword: "NewPassword",
permission: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

Test logic error: This test is named SaveDetailsAsync_CipherKeyNotChangedWithoutPermission but passes permission: true on this line.

The test should pass permission: false to properly validate the scenario where a user without hidden password permission attempts to change the key. Currently, this test is not validating the fix described in PM-29017.

Suggested change
permission: true,
permission: false,

@github-actions
Copy link
Contributor

Logo
Checkmarx One – Scan Summary & Details102adfc6-bd48-4795-a6a4-48b995b578eb

Great job! No new security vulnerabilities introduced in this pull request

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.

2 participants