Skip to content

Conversation

@eliykat
Copy link
Member

@eliykat eliykat commented Dec 16, 2025

🎟️ Tracking

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

📔 Objective

Bug

When organizations upgraded their plan, the server unconditionally overwrote the organization's public and private keys with whatever the client sent, including null values. This caused existing organizations to lose their encryption keys during plan changes.

Fix

Replaced unconditional assignment with the existing BackfillPublicPrivateKeys extension method, which only sets keys if:

  1. New keys are provided (not null/whitespace)
  2. Organization doesn't already have keys

This preserves the legacy migration behavior for old organizations created without keypairs while protecting existing keys from being overwritten.

Additionally, the logic in BackfillPublicPrivateKeys was strengthened so that both keys are updated together or not at all.

Related Changes

  • Updated core models (OrganizationUpgrade, OrganizationUpdateRequest) to use PublicKeyEncryptionKeyPairData for keys (this is KM Team's recommended DTO)
  • Updated BackfillPublicPrivateKeys extension method to accept PublicKeyEncryptionKeyPairData so it can be used from multiple places

📸 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

@github-actions
Copy link
Contributor

github-actions bot commented Dec 16, 2025

Logo
Checkmarx One – Scan Summary & Details48f668d0-bd25-42ec-a55d-ee7a69f9c515

New Issues (2)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1170
detailsMethod at line 1170 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
ID: ydwqMeYmBkmGAeG%2FbyXCmFNSIz4%3D
Attack Vector
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1060
detailsMethod at line 1060 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
ID: NBqS3wtj%2BwcjukpYL1K2xj0Y2Fw%3D
Attack Vector
Fixed Issues (1)

Great job! The following issues were fixed in this Pull Request

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 208

@codecov
Copy link

codecov bot commented Dec 16, 2025

Codecov Report

❌ Patch coverage is 92.85714% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.73%. Comparing base (96622d7) to head (5ee3e0d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...st/Organizations/OrganizationCreateRequestModel.cs 0.00% 2 Missing ⚠️
...rganizations/OrganizationNoPaymentCreateRequest.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6738      +/-   ##
==========================================
- Coverage   58.58%   54.73%   -3.86%     
==========================================
  Files        1920     1920              
  Lines       85264    85226      -38     
  Branches     7632     7626       -6     
==========================================
- Hits        49953    46645    -3308     
- Misses      33465    36808    +3343     
+ Partials     1846     1773      -73     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@eliykat eliykat marked this pull request as ready for review December 17, 2025 04:05
@eliykat eliykat requested review from a team as code owners December 17, 2025 04:05
Comment on lines -259 to -270
organization.UseGroups = newPlan.HasGroups;
organization.UseDirectory = newPlan.HasDirectory;
organization.UseEvents = newPlan.HasEvents;
organization.UseTotp = newPlan.HasTotp;
organization.Use2fa = newPlan.Has2fa;
organization.UseApi = newPlan.HasApi;
organization.UseSso = newPlan.HasSso;
organization.UseOrganizationDomains = newPlan.HasOrganizationDomains;
organization.UseKeyConnector = newPlan.HasKeyConnector ? organization.UseKeyConnector : false;
organization.UseScim = newPlan.HasScim;
organization.UseResetPassword = newPlan.HasResetPassword;
organization.SelfHost = newPlan.HasSelfHost;
Copy link
Member Author

Choose a reason for hiding this comment

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

Unrelated fix: remove duplicate property assignments.

@claude
Copy link
Contributor

claude bot commented Dec 17, 2025

Claude finished @eliykat's task in 2m 1s —— View job


Code Review Complete

  • Analyzed PR changes
  • Reviewed security implications
  • Checked test coverage
  • Evaluated implementation approach

Overall Assessment: APPROVE

Reviewed security-critical fix for organization encryption key handling during plan upgrades across 18 files. The BackfillPublicPrivateKeys extension method correctly implements atomic key pair updates (both keys or neither), preventing data loss while maintaining backward compatibility for legacy organizations. The switch to PublicKeyEncryptionKeyPairData DTO provides strong type safety with required field validation. Test coverage comprehensively validates all key state transitions.


@claude
Copy link
Contributor

claude bot commented Dec 17, 2025

Overall Assessment: APPROVE

Reviewed security-critical fix for organization encryption key handling during plan upgrades. The implementation correctly prevents existing keys from being overwritten and maintains proper atomicity. Test coverage is comprehensive.

@JimmyVo16
Copy link
Contributor

Just FYI, this will be the first thing on my todo list tomorrow. Sorry, I couldn’t get to it sooner.

@eliykat eliykat merged commit 67534e2 into main Dec 26, 2025
45 checks passed
@eliykat eliykat deleted the ac/pm-29556/server-changing-organization-plan-nulls-out-public-and-private-keys branch December 26, 2025 00:13
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.

5 participants