Prevent ProtectedData crash on Linux by catching PlatformNotSupportedException#384
Merged
Merged
Conversation
ProtectedData.Protect/Unprotect compiles for .NET 6 but throws at runtime on Linux. Wrap both calls in a try/catch: EncryptPassword returns null on failure (same effect as RememberPassword=false), and DecryptPassword returns its input unmodified so a partially-stored value does not crash the caller. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Returning the input unmodified would pass a raw DPAPI blob as a password credential when settings are migrated from Windows to Linux, causing silent auth failures. Returning null matches the "no saved password" semantics, consistent with how EncryptPassword already behaves on unsupported platforms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ProtectedData.Unprotect throws CryptographicException when the data was encrypted by a different Windows user account, after an OS reinstall, or if the stored value is corrupted. The correct response is the same as for PlatformNotSupportedException: return null and force the user to re-enter their password. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ecryptPassword Any failure to encrypt or decrypt a saved password now resolves to null (treat as no saved password) rather than crashing the caller: - EncryptPassword: CryptographicException from a broken DPAPI subsystem would otherwise abort the entire SaveUserSettings call, not just the password field. - DecryptPassword: FormatException from Convert.FromBase64String covers the case where the stored value is not valid Base64 (manual file corruption). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
|
If we know that it's going to throw then we should use |
…SupportedException Replace the PlatformNotSupportedException catch with an explicit !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) early return, following the same pattern ProtectedData itself uses internally. Avoids exceptions as control flow for a predictable platform condition. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
imnasnainaec
commented
Jun 24, 2026
imnasnainaec
left a comment
Contributor
Author
There was a problem hiding this comment.
Good point! Done.
@imnasnainaec made 1 comment.
Reviewable status: 0 of 3 files reviewed, all discussions resolved (waiting on rmunn).
net462 (.NET Framework) doesn't have RuntimeInformation; guard the platform check with #if !NETFRAMEWORK. The check is also redundant there since net462 only runs on Windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
Author
|
A possible follow-up issue/pr would be to completely disable the remember-password checkbox on Linux so that it's not a silent no-op. |
hahn-kev
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
`ServerSettingsModel.EncryptPassword` and `DecryptPassword` use `System.Security.Cryptography.ProtectedData`, which compiles for .NET 6 but throws `PlatformNotSupportedException` at runtime on Linux.
Guard both methods with `!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)` and return `null` early on non-Windows platforms, following the same pattern ProtectedData itself uses. This avoids using exceptions for predictable control flow.
On Windows, both methods also catch runtime failures:
Known limitation: on non-Windows platforms, `RememberPassword = true` silently becomes a no-op — the preference is lost on restart with no UI feedback. Addressing that properly (disabling the checkbox or surfacing a message on unsupported platforms) requires UI changes and is left for a follow-up.
Trade-off: when `EncryptPassword` catches `CryptographicException` on Windows and returns `null`, `SaveUserSettings` will store `null` and call `Settings.Default.Save()`, permanently wiping a previously persisted password. Before this PR, the exception would propagate and `Save()` would never execute, preserving the old encrypted value. `CryptographicException` from `ProtectedData.Protect` is rare on healthy Windows systems, and the password remains available in-memory via `PasswordForSession` for the current session, but the user will not realize their saved password was dropped until the next restart.
Mitigates #298
Devin review: https://app.devin.ai/review/sillsdev/chorus/pull/384
This change is