Skip to content

feat: add master password support, credential sets UI, and FrmPassword fixes#3229

Open
yosale2011 wants to merge 3 commits intomRemoteNG:v1.78.2-devfrom
yosale2011:feature/master-password
Open

feat: add master password support, credential sets UI, and FrmPassword fixes#3229
yosale2011 wants to merge 3 commits intomRemoteNG:v1.78.2-devfrom
yosale2011:feature/master-password

Conversation

@yosale2011
Copy link
Copy Markdown

Summary

  • Add master password support with encrypted verifier storage and startup unlock flow
  • Add credential sets manager UI for managing internal credential sets
  • Add master password manager form for setting/changing/removing master password
  • Fix FrmPassword CS0535 build error (missing IKeyProvider.GetKey())
  • Bring password dialog to foreground on startup
  • Improve error handling in credential deserialization

Master Password Feature

  • New MasterPasswordService class for setting, verifying, and removing master passwords
  • New StartupUnlockService to prompt for master password on application startup
  • XmlKeyValidator for validating encryption keys against XML files
  • Session-based encryption key management in Runtime.cs

Credential Sets Feature

  • New CredentialSetsManager form for viewing and managing credential sets
  • Added "Credential Sets" menu item under Tools menu
  • Internal credential set support with default repository handling
  • CredentialSetTypeConverter for property grid integration

FrmPassword UI Fixes

  • Implemented parameterless GetKey() to satisfy IKeyProvider interface (build fix)
  • Added TopMost/BringToFront/Activate to ensure dialog appears in foreground
  • Changed StartPosition from CenterParent to CenterScreen
  • Fixed OK button to properly validate and close

Test plan

  • Build succeeds without errors
  • Password dialog appears in foreground when application starts
  • Master password can be set, verified, and removed
  • Credential sets can be managed through the new UI
  • Existing connections load correctly without master password configured

…FrmPassword fixes

- Add MasterPasswordService with encrypted verifier storage
- Add StartupUnlockService for master password prompt on startup
- Add XmlKeyValidator for encryption key validation
- Add credential sets manager UI and master password manager form
- Fix FrmPassword CS0535 build error (missing IKeyProvider.GetKey())
- Bring password dialog to foreground on startup
- Improve error handling in credential deserialization

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add master password support, credential sets UI, and password dialog improvements

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add comprehensive master password support with encrypted verifier storage and startup unlock flow
• Implement credential sets manager UI for managing internal credential sets with add, edit, delete
  operations
• Add master password manager form for setting, changing, and removing master passwords
• Fix FrmPassword CS0535 build error by implementing missing IKeyProvider.GetKey() method
• Improve password dialog visibility by adding TopMost, BringToFront(), Activate() and
  changing StartPosition to CenterScreen
• Integrate runtime encryption key management into connection and credential deserialization flows
• Add InternalCredentialSet external credential provider support to RDP and PuTTY protocols
• Enhance error handling in credential deserialization with graceful fallback for corrupted files
• Add property grid integration for credential set selection via CredentialSetTypeConverter
• Implement XmlKeyValidator utility for validating encryption keys against XML files
• Add localization strings for credential sets feature and master password UI
• Update project configuration with application manifest, high DPI mode settings, and dependency
  updates
Diagram
flowchart LR
  A["User Startup"] -->|"EnsureStartupUnlocked()"| B["StartupUnlockService"]
  B -->|"Check master password"| C["MasterPasswordService"]
  C -->|"Validate with XmlKeyValidator"| D["Encryption Key"]
  D -->|"Set session key"| E["Runtime.EncryptionKey"]
  E -->|"Decrypt connections/credentials"| F["XmlConnectionsDeserializer"]
  F -->|"Load with key"| G["Connection Records"]
  H["Tools Menu"] -->|"Open"| I["CredentialSetsManager"]
  H -->|"Open"| J["MasterPasswordManager"]
  I -->|"Manage"| K["Internal Credential Sets"]
  J -->|"Configure"| C
  L["RDP/PuTTY Protocol"] -->|"Resolve credentials"| K
Loading

Grey Divider

File Changes

1. mRemoteNG/Connection/Protocol/RDP/RdpProtocol.cs ✨ Enhancement +1034/-1011

Add internal credential set support to RDP protocol

• Added support for InternalCredentialSet external credential provider in both SetRdGateway()
 and SetCredentials() methods
• Integrated CredentialSetResolver.Resolve() to fetch credentials from internal credential sets
• Added error handling for credential set resolution failures

mRemoteNG/Connection/Protocol/RDP/RdpProtocol.cs


2. mRemoteNG/Connection/Protocol/PuttyBase.cs ✨ Enhancement +31/-49

Add credential set support and simplify PuTTY window handling

• Added support for InternalCredentialSet external credential provider with
 CredentialSetResolver.Resolve() integration
• Removed null-coalescing operators (?.) from ExternalCredentialProvider checks for consistency
• Removed window styling code that stripped title bar and frame border from embedded PuTTY windows
• Simplified window positioning logic with scaled frame border calculations
• Removed process minimization and window hiding logic

mRemoteNG/Connection/Protocol/PuttyBase.cs


3. mRemoteNG/UI/Forms/CredentialSetsManager.cs ✨ Enhancement +350/-0

New credential sets manager UI form

• New form for managing internal credential sets with add, edit, delete, and save functionality
• Displays credentials in a list view with columns for title, username, and domain
• Implements credential editing UI with validation for required fields
• Handles credential repository persistence and reference counting
• Integrates with theme manager and language system

mRemoteNG/UI/Forms/CredentialSetsManager.cs


View more (26)
4. mRemoteNG/App/Runtime.cs ✨ Enhancement +197/-2

Add master password and credential service initialization

• Added master password session management with _masterPasswordKey field and
 HasActiveMasterPasswordSession property
• Implemented InitializeCredentialService() and EnsureDefaultCredentialRepository() for
 credential system initialization
• Added encryption key management methods: SetEncryptionKey(), ResetEncryptionKey(),
 SetMasterPasswordSession(), ClearMasterPasswordSession()
• Implemented credential repository key resolution and migration logic
• Added synchronization of loaded repositories when encryption key changes

mRemoteNG/App/Runtime.cs


5. mRemoteNG/App/MasterPasswordService.cs ✨ Enhancement +168/-0

New master password service implementation

• New service for managing master password configuration with set, verify, and remove operations
• Stores encrypted password verifier in application settings using XML format
• Implements TryUnlock() to verify master password and establish session
• Handles re-encryption of settings when master password changes
• Supports migration of encrypted credentials to new encryption key

mRemoteNG/App/MasterPasswordService.cs


6. mRemoteNG/UI/Forms/MasterPasswordManager.cs ✨ Enhancement +172/-0

New master password manager UI form

• New form for setting, changing, and removing master password
• Displays current master password status with contextual descriptions
• Prompts for current password verification before allowing changes
• Validates new password length (minimum 3 characters) and confirmation matching
• Integrates with theme manager and uses MasterPasswordService for operations

mRemoteNG/UI/Forms/MasterPasswordManager.cs


7. mRemoteNG/UI/Menu/msMain/ToolsMenu.cs ✨ Enhancement +40/-2

Add credential sets and master password menu items

• Added "Credential Sets" menu item under Tools menu with key icon
• Added "Master Password" menu item under Tools menu with key icon
• Implemented click handlers to open CredentialSetsManager and MasterPasswordManager dialogs
• Updated ApplyLanguage() to include new menu items

mRemoteNG/UI/Menu/msMain/ToolsMenu.cs


8. mRemoteNG/App/ProgramRoot.cs Miscellaneous +7/-27

Refactor high DPI mode initialization and runtime check

• Moved Application.SetHighDpiMode() call from Main() to StartApplication() method
• Simplified .NET runtime check error handling by removing URL validation logic
• Removed conditional logic for disabled download button based on URL validity

mRemoteNG/App/ProgramRoot.cs


9. mRemoteNG/Config/Serializers/ConnectionSerializers/Sql/DataTableDeserializer.cs ✨ Enhancement +9/-9

Enable external credential provider SQL deserialization

• Uncommented external credential provider deserialization for ExternalCredentialProvider and
 RDGatewayExternalCredentialProvider
• Uncommented UserViaAPI and RDGatewayUserViaAPI field deserialization
• Uncommented inheritance flag deserialization for credential provider and API user fields

mRemoteNG/Config/Serializers/ConnectionSerializers/Sql/DataTableDeserializer.cs


10. mRemoteNG/Credential/CredentialSetTypeConverter.cs ✨ Enhancement +120/-0

New credential set type converter for property grid

• New type converter for property grid integration of credential set selection
• Provides dropdown list of available credential sets by title
• Handles conversion between display titles and credential GUIDs
• Supports both GUID and title-based lookups with fallback handling

mRemoteNG/Credential/CredentialSetTypeConverter.cs


11. mRemoteNG/Connection/AbstractConnectionRecord.cs ✨ Enhancement +1137/-1134

Add credential set type converter to connection properties

• Added CredentialSetTypeConverter attribute to UserViaAPI property for property grid dropdown
 support
• Added CredentialSetTypeConverter attribute to RDGatewayUserViaAPI property for property grid
 dropdown support

mRemoteNG/Connection/AbstractConnectionRecord.cs


12. mRemoteNG/Config/CredentialRecordLoader.cs Error handling +11/-2

Add error handling to credential record loader

• Added try-catch error handling to Load() method
• Returns empty credential collection on deserialization failures instead of throwing exceptions
• Allows system to initialize properly even when credential file is missing or corrupted

mRemoteNG/Config/CredentialRecordLoader.cs


13. mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs ✨ Enhancement +568/-563

Integrate runtime encryption key into connection deserialization

• Integrated Runtime.EncryptionKey into deserialization flow to support master password sessions
• Modified LoadXmlConnectionData() to create a startup root node with encryption key from runtime
• Updated Deserialize() to set _rootNodeInfo.PasswordString from Runtime.EncryptionKey before
 decryptor creation
• Improved error handling for credential deserialization with graceful fallback

mRemoteNG/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs


14. mRemoteNG/Security/XmlKeyValidator.cs ✨ Enhancement +121/-0

Add XML key validator for master password support

• New utility class for validating encryption keys against XML connection and credential files
• Provides three validation methods: ConnectionFileRequiresPassword(), ConnectionFileUsesKey(),
 CredentialsFileUsesKey()
• Uses CryptoProviderFactoryFromXml to build appropriate cryptography providers
• Handles XML parsing errors gracefully with try-catch blocks

mRemoteNG/Security/XmlKeyValidator.cs


15. mRemoteNG/UI/Forms/frmMain.cs ✨ Enhancement +17/-26

Add startup unlock flow and credential service initialization

• Added StartupUnlockService.EnsureStartupUnlocked() call in FrmMain_Load() to prompt for master
 password on startup
• Added Runtime.InitializeCredentialService() call before loading connections
• Refactored PromptForUpdatesPreference() method with simplified logic and fixed bitwise operator
 usage

mRemoteNG/UI/Forms/frmMain.cs


16. mRemoteNG/Language/Language.Designer.cs ✨ Enhancement +90/-0

Add localization strings for credential sets feature

• Added new localized string ECPInternalCredentialSet for credential set provider type
• Added credential sets UI related strings: CredentialSetsManager, CredentialDetails, Edit,
 Confirm, Error
• Added credential deletion confirmation strings with reference counting
• Added CredentialTitleRequired validation message and CredentialSetsMenuItem for Tools menu

mRemoteNG/Language/Language.Designer.cs


17. mRemoteNG/Config/Serializers/XmlConnectionsDecryptor.cs ✨ Enhancement +42/-6

Enhance authentication with master password session support

• Refactored ConnectionsFileIsAuthentic() to handle master password sessions and runtime
 encryption key management
• Added TryDecryptProtectionMarker() helper method for safe decryption attempts
• Integrated Runtime.SetEncryptionKey() and Runtime.ResetEncryptionKey() calls based on
 authentication results
• Improved logic to detect unprotected vs protected files and set appropriate encryption keys

mRemoteNG/Config/Serializers/XmlConnectionsDecryptor.cs


18. mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialRecordDeserializer.cs Error handling +37/-16

Improve credential deserialization error handling

• Added comprehensive error handling with try-catch to gracefully handle invalid credential files
• Changed ValidateSchemaVersion() to IsValidSchemaVersion() returning boolean instead of
 throwing
• Returns empty credential array instead of throwing exceptions on parsing failures
• Improved robustness for uninitialized or corrupted credential files

mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialRecordDeserializer.cs


19. mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs Error handling +28/-3

Add error handling for credential file decryption

• Added error handling wrapper around decryption process returning empty collection on failure
• Added validation for Auth attribute presence before decryption attempts
• Returns empty credentials gracefully when file lacks proper initialization or has wrong format
• Improved handling of uninitialized credential files

mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs


20. mRemoteNG/UI/Forms/FrmPassword.cs 🐞 Bug fix +16/-5

Fix password dialog interface and improve visibility

• Implemented parameterless GetKey() method satisfying IKeyProvider interface requirement
• Added overload GetKey(IWin32Window owner) for owner window support
• Added icon assignment from application executable in constructor
• Enhanced dialog visibility with TopMost, BringToFront(), Activate() calls in
 FrmPassword_Load()
• Fixed OK button to validate and close dialog properly

mRemoteNG/UI/Forms/FrmPassword.cs


21. mRemoteNG/App/StartupUnlockService.cs ✨ Enhancement +77/-0

Add startup unlock service for master password flow

• New service class for handling startup unlock flow with master password and connection file
 password
• EnsureStartupUnlocked() method prompts for master password first, then connection file password
 if needed
• Uses XmlKeyValidator to check if connection file requires password and validate provided keys
• Manages Runtime.EncryptionKey based on master password session state

mRemoteNG/App/StartupUnlockService.cs


22. mRemoteNG/Tools/MiscTools.cs ✨ Enhancement +8/-2

Add owner window support to password dialog

• Added overload PasswordDialog(IWin32Window? owner, string? passwordName, bool verify) supporting
 owner window parameter
• Existing parameterless PasswordDialog() now delegates to new overload with null owner
• Passes owner window to FrmPassword.GetKey() for proper dialog parenting

mRemoteNG/Tools/MiscTools.cs


23. mRemoteNG/UI/Controls/ConnectionInfoPropertyGrid/ConnectionInfoPropertyGrid.cs ✨ Enhancement +13/-0

Add internal credential set UI support

• Added special handling for InternalCredentialSet external credential provider type
• Hides manual credential fields (Username, Password, Domain) when using internal credential sets
• Hides vault-related fields for credential set provider
• Added Runtime.SetEncryptionKey() and Runtime.ResetEncryptionKey() calls in
 UpdateRootInfoNode()

mRemoteNG/UI/Controls/ConnectionInfoPropertyGrid/ConnectionInfoPropertyGrid.cs


24. mRemoteNG/Properties/OptionsSecurityPage.Designer.cs Formatting +3/-3

Clean up whitespace formatting

• Removed trailing whitespace from property definitions
• Formatting cleanup for consistency

mRemoteNG/Properties/OptionsSecurityPage.Designer.cs


25. mRemoteNG/UI/Forms/FrmPassword.Designer.cs ✨ Enhancement +2/-2

Update password dialog display settings

• Changed ShowIcon from false to true to display application icon
• Changed StartPosition from CenterParent to CenterScreen for better visibility

mRemoteNG/UI/Forms/FrmPassword.Designer.cs


26. mRemoteNG/Properties/OptionsSecurityPage.Extensions.cs ✨ Enhancement +14/-0

Add master password verifier setting extension

• New extension class adding MasterPasswordVerifier setting to OptionsSecurityPage
• Stores encrypted master password verifier for validation on startup
• User-scoped setting with empty default value

mRemoteNG/Properties/OptionsSecurityPage.Extensions.cs


27. mRemoteNG/UI/Forms/CredentialSetsManager.resx ✨ Enhancement +121/-0

Add credential sets manager resource file

• New resource file for credential sets manager form
• Contains standard ResX schema structure for Windows Forms resources

mRemoteNG/UI/Forms/CredentialSetsManager.resx


28. mRemoteNG/mRemoteNG.csproj ⚙️ Configuration changes +13/-4

Update project configuration and dependencies

• Added ApplicationManifest and ApplicationHighDpiMode project properties
• Conditioned COM reference for MSTSCLib to Visual Studio builds only
• Added NuGet package reference AxMSTSCLib for dotnet CLI builds
• Added platform-specific NuGet packages for .NET Core support
• Updated CEF runtime versions from 145.0.26 to 144.0.12 for both x64 and arm64
• Made TextTemplating targets import conditional on file existence

mRemoteNG/mRemoteNG.csproj


29. mRemoteNG/Properties/OptionsSecurityPage.settings ⚙️ Configuration changes +4/-1

Add master password verifier setting

• Added new MasterPasswordVerifier setting of type System.String with empty default value
• Setting is user-scoped for storing encrypted master password verification data

mRemoteNG/Properties/OptionsSecurityPage.settings


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 21, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. AxMSTSCLib version missing🐞 Bug ✓ Correctness
Description
Central package management is enabled, but the new PackageReference to AxMSTSCLib has no
corresponding PackageVersion, which will break non-VisualStudio (dotnet CLI) restores/builds.
Code

mRemoteNG/mRemoteNG.csproj[R129-132]

+  <!-- NuGet package for dotnet CLI builds -->
+  <ItemGroup Condition="'$(BuildingInsideVisualStudio)' != 'true'">
+    <PackageReference Include="AxMSTSCLib" />
+  </ItemGroup>
Evidence
The project uses central package management, but adds a versionless AxMSTSCLib PackageReference only
for non-VS builds; without a matching PackageVersion entry, restore/build will fail under central
management.

mRemoteNG/mRemoteNG.csproj[117-132]
Directory.Packages.props[1-5]
Directory.Packages.props[7-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`mRemoteNG/mRemoteNG.csproj` adds `&amp;amp;lt;PackageReference Include=&amp;amp;quot;AxMSTSCLib&amp;amp;quot; /&amp;amp;gt;` for dotnet CLI builds while the repo uses central package management (`ManagePackageVersionsCentrally=true`). There is no `PackageVersion` entry for `AxMSTSCLib`, which typically causes NuGet restore/build failures.
### Issue Context
Central package management requires every `PackageReference` to have a corresponding `PackageVersion` in `Directory.Packages.props` (or specify `Version=` inline).
### Fix Focus Areas
- mRemoteNG/mRemoteNG.csproj[129-132]
- Directory.Packages.props[1-40]
### Suggested fix
Add a central version entry, e.g.:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Credentials can be wiped🐞 Bug ⛯ Reliability
Description
Credential repository loading/decryption now swallows all exceptions and returns an empty set, and
Runtime’s key migration/sync logic can later save that empty set back to disk, silently overwriting
valid credentials after a wrong key/corruption.
Code

mRemoteNG/Config/CredentialRecordLoader.cs[R28-40]

      public IEnumerable<ICredentialRecord> Load(SecureString key)
      {
-            string serializedCredentials = _dataProvider.Load();
-            return _deserializer.Deserialize(serializedCredentials, key);
+            try
+            {
+                string serializedCredentials = _dataProvider.Load();
+                return _deserializer.Deserialize(serializedCredentials, key);
+            }
+            catch (Exception)
+            {
+                // If loading fails for any reason (file missing, corrupt, etc.),
+                // return empty collection to allow the system to initialize properly.
+                return Array.Empty<ICredentialRecord>();
+            }
Evidence
Multiple credential load/decrypt/parse components now return empty on any error, making a decryption
failure indistinguishable from a truly empty repository. Runtime then calls
SaveCredentials(EncryptionKey) during repository key migration/synchronization, which persists the
current in-memory records (possibly empty) via the saver.

mRemoteNG/Config/CredentialRecordLoader.cs[28-40]
mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs[26-42]
mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs[45-59]
mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialRecordDeserializer.cs[16-43]
mRemoteNG/App/Runtime.cs[213-245]
mRemoteNG/Config/CredentialRecordSaver.cs[27-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Credential loading/decryption/parsing now catches broad exceptions and returns an empty credential set. This can convert a *failure* (wrong key, corrupted file, invalid format) into “no credentials”. Later, `Runtime` can call `repository.SaveCredentials(EncryptionKey)` during key migration/sync, which will persist the empty in-memory set and overwrite the on-disk repository.
### Issue Context
A load/decrypt failure should be surfaced and should prevent marking the repository as successfully loaded or prevent subsequent save/migration operations.
### Fix Focus Areas
- mRemoteNG/Config/CredentialRecordLoader.cs[28-40]
- mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs[26-42]
- mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialPasswordDecryptorDecorator.cs[45-59]
- mRemoteNG/Config/Serializers/CredentialSerializer/XmlCredentialRecordDeserializer.cs[16-43]
- mRemoteNG/App/Runtime.cs[213-245]
### Suggested fix
- Only treat *file missing/uninitialized* as empty; for decrypt/parse/schema errors:
- log/show an error,
- return a failure indicator (e.g., throw a specific exception or return a Result type),
- ensure the repository is not set to `IsLoaded=true` on failure,
- and/or guard `SaveCredentials`/migration to skip repositories whose last load failed.
- Consider distinguishing “uninitialized credentials file” from “invalid credentials file” instead of returning `string.Empty`/empty collection for both.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. TypeConverter clears UserViaAPI🐞 Bug ✓ Correctness
Description
CredentialSetTypeConverter.ConvertFrom returns an empty string for values that are neither GUIDs nor
known credential titles, so entering a custom UserViaAPI value will be converted to empty and saved,
breaking non-internal credential provider configurations.
Code

mRemoteNG/Credential/CredentialSetTypeConverter.cs[R64-91]

+        public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context)
+        {
+            // Allow custom values for other external credential providers (like DelineaSecretServer)
+            // The dropdown will still show available credential sets for InternalCredentialSet
+            return false;
+        }
+
+        public override bool GetStandardValuesSupported(ITypeDescriptorContext? context)
+        {
+            return true;
+        }
+
+        public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+        {
+            if (value is string stringValue)
+            {
+                // If it's already a GUID, return it as-is
+                if (Guid.TryParse(stringValue, out _))
+                    return stringValue;
+
+                // Otherwise, look up the GUID from the title
+                Dictionary<string, string> map = GetCredentialSetMap();
+                if (map.TryGetValue(stringValue, out string? guid))
+                    return guid;
+
+                // Return empty string if not found
+                return string.Empty;
+            }
Evidence
The type converter explicitly allows non-exclusive values, but its ConvertFrom path drops any
unknown string to string.Empty. The converter is applied to UserViaAPI and
RDGatewayUserViaAPI, so editing those fields in the property grid can erase values that are not
credential-set titles/GUIDs.

mRemoteNG/Credential/CredentialSetTypeConverter.cs[64-91]
mRemoteNG/Connection/AbstractConnectionRecord.cs[233-240]
mRemoteNG/Connection/AbstractConnectionRecord.cs[640-648]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CredentialSetTypeConverter.ConvertFrom(...)` returns `string.Empty` when the provided string is not a GUID and not found in the credential title→GUID map. In the property grid, this will replace a user-entered custom value with an empty string.
### Issue Context
The converter sets `GetStandardValuesExclusive` to `false` (custom values allowed), but `ConvertFrom` contradicts that by clearing unknown inputs.
### Fix Focus Areas
- mRemoteNG/Credential/CredentialSetTypeConverter.cs[64-91]
- mRemoteNG/Connection/AbstractConnectionRecord.cs[233-240]
- mRemoteNG/Connection/AbstractConnectionRecord.cs[640-648]
### Suggested fix
- In `ConvertFrom`, if the string is not a GUID and not a known title, **return the original stringValue** rather than `string.Empty`.
- Optionally, only perform title→GUID mapping when the instance’s provider is `InternalCredentialSet` (inspect `context?.Instance` as `ConnectionInfo`/record and check `ExternalCredentialProvider` / `RDGatewayExternalCredentialProvider`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. PuTTY orphan risk on crash 🐞 Bug ⛯ Reliability
Description
PuTTY process startup no longer registers the spawned process with ChildProcessTracker, so
crash/abrupt-exit cleanup via the Job Object is no longer applied and PuTTY can be orphaned.
Code

mRemoteNG/Connection/Protocol/PuttyBase.cs[R302-306]

              PuttyProcess.EnableRaisingEvents = true;
              PuttyProcess.Exited += ProcessExited;
-                // Start the process minimized for non-PuTTYNG so the window
-                // does not flash at its default position on screen before
-                // being reparented into the mRemoteNG panel.
-                if (!_isPuttyNg)
-                {
-                    PuttyProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
-                }
-
              PuttyProcess.Start();
-                ChildProcessTracker.AddProcess(PuttyProcess);
              PuttyProcess.WaitForInputIdle(Properties.OptionsAdvancedPage.Default.MaxPuttyWaitTime * 1000);
Evidence
ChildProcessTracker is explicitly designed to ensure child processes are terminated when the parent
exits by assigning them to a Job Object. PuttyBase still spawns the PuTTY process but no longer adds
it to this tracker, and there are no other references to ChildProcessTracker usage elsewhere in the
codebase.

mRemoteNG/Connection/Protocol/PuttyBase.cs[302-306]
mRemoteNG/Tools/ChildProcessTracker.cs[8-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PuttyBase.Connect()` starts `PuttyProcess` but does not add it to `ChildProcessTracker`. `ChildProcessTracker` exists to put child processes into a Windows Job Object with `KILL_ON_JOB_CLOSE` so they are terminated if mRemoteNG crashes/exits.
### Issue Context
Without this registration, PuTTY processes may remain running if mRemoteNG terminates unexpectedly.
### Fix Focus Areas
- mRemoteNG/Connection/Protocol/PuttyBase.cs[302-306]
- mRemoteNG/Tools/ChildProcessTracker.cs[8-54]
### Suggested fix
Call `ChildProcessTracker.AddProcess(PuttyProcess);` immediately after `PuttyProcess.Start()` (or as soon as the handle is available), unless there is a documented replacement cleanup mechanism.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. HighDPI set after dialogs 🐞 Bug ⛯ Reliability
Description
Application.SetHighDpiMode is now called in StartApplication, but runtime-check UI (download/cancel
dialogs) can be shown earlier, so those dialogs may render without the intended PerMonitorV2 DPI
configuration.
Code

mRemoteNG/App/ProgramRoot.cs[R52-55]

          var (latestRuntimeVersion, downloadUrl) = DotNetRuntimeCheck.GetLatestAvailableDotNetVersionAsync().GetAwaiter().GetResult();
-            bool validDownloadUrl = Uri.TryCreate(downloadUrl, UriKind.Absolute, out var downloadUri) && downloadUri.Scheme == Uri.UriSchemeHttps;
          if (string.IsNullOrEmpty(installedVersion))
          {
              try
Evidence
MainAsync shows dialogs during runtime checks before calling StartApplication. High DPI mode is only
set inside StartApplication, after these dialogs can already have been displayed.

mRemoteNG/App/ProgramRoot.cs[49-77]
mRemoteNG/App/ProgramRoot.cs[150-155]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Application.SetHighDpiMode(PerMonitorV2)` is called in `StartApplication()`, but runtime checks in `MainAsync()` can show dialogs first. Those earlier dialogs may not benefit from the intended DPI mode.
### Issue Context
This impacts UX (scaling/hit-testing) for the startup/runtime-check dialogs.
### Fix Focus Areas
- mRemoteNG/App/ProgramRoot.cs[49-77]
- mRemoteNG/App/ProgramRoot.cs[150-155]
### Suggested fix
Move `Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);` back to the earliest possible point in `Main()` (before any dialogs or other WinForms UI is shown), or ensure an equivalent early initialization path runs before runtime-check dialogs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread mRemoteNG/mRemoteNG.csproj
Comment thread mRemoteNG/Config/CredentialRecordLoader.cs Outdated
Comment thread mRemoteNG/Credential/CredentialSetTypeConverter.cs
Yosale2011 and others added 2 commits March 21, 2026 14:27
… converter

- Add AxMSTSCLib PackageVersion (1.0.1) to Directory.Packages.props for
  central package management compatibility with dotnet CLI builds
- Remove catch-all exception handlers in credential loading pipeline to
  prevent silent data loss: decryption/parse errors now propagate,
  keeping IsLoaded=false and preventing SaveCredentials from overwriting
  valid credentials with an empty set
- Fix CredentialSetTypeConverter.ConvertFrom to return original value
  instead of empty string for unknown inputs, preserving custom
  credential provider values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…CredentialSet enum

- Create CredentialSetsManager.Designer.cs with Form inheritance and
  all UI controls referenced by CredentialSetsManager.cs
- Create CredentialSetResolver class for resolving credentials by
  GUID or title from the credential catalog
- Add InternalCredentialSet value to ExternalCredentialProvider enum

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@yosale2011
Copy link
Copy Markdown
Author

Update: Build fixes added

Added missing files to fix build errors:

  • CredentialSetsManager.Designer.cs — Form designer with all UI controls
  • CredentialSetResolver.cs — Resolves credentials by GUID or title
  • ExternalCredentialProviderSelector.cs — Added InternalCredentialSet enum value

Build now succeeds with 0 errors.

@sonarqubecloud
Copy link
Copy Markdown

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.

1 participant