Compare commits

..

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
860a7689c5 Add URL scheme validation to prevent command injection via Process.Start
- HelpMenu.cs: Add https/http scheme validation to OpenUrl() to prevent
  custom URI scheme exploitation
- UpdateWindow.cs: Add scheme validation alongside existing IsFile/IsUnc/IsLoopback
  checks to only allow http/https URLs
- ProgramRoot.cs: Add https:// prefix validation for network-fetched downloadUrl
  before passing to Process.Start with UseShellExecute=true

Co-authored-by: Kvarkas <3611964+Kvarkas@users.noreply.github.com>
2026-02-25 17:36:46 +00:00
copilot-swe-agent[bot]
b65686823c Initial plan 2026-02-25 17:29:05 +00:00
5 changed files with 26 additions and 19 deletions

View File

@@ -64,7 +64,9 @@ namespace mRemoteNG.App
{
try
{
Process.Start(new ProcessStartInfo(fileName: downloadUrl) { UseShellExecute = true });
if (!string.IsNullOrEmpty(downloadUrl) &&
downloadUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
Process.Start(new ProcessStartInfo(fileName: downloadUrl) { UseShellExecute = true });
}
catch (Exception ex)
{

View File

@@ -641,27 +641,20 @@ namespace mRemoteNG.Connection.Protocol.RDP
_rdpClient.UserName = userName;
}
// Restricted Admin and Remote Credential Guard modes use the current user's Kerberos
// credentials and do not forward explicit passwords to the remote host.
// Skipping password assignment avoids potential NTLM fallback attempts that would
// fail for accounts in the AD Protected Users security group.
if (!connectionInfo.UseRestrictedAdmin && !connectionInfo.UseRCG)
if (string.IsNullOrEmpty(password))
{
if (string.IsNullOrEmpty(password))
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
{
if (Properties.OptionsCredentialsPage.Default.EmptyCredentials == "custom")
if (Properties.OptionsCredentialsPage.Default.DefaultPassword != "")
{
if (Properties.OptionsCredentialsPage.Default.DefaultPassword != "")
{
LegacyRijndaelCryptographyProvider cryptographyProvider = new();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
}
LegacyRijndaelCryptographyProvider cryptographyProvider = new();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Properties.OptionsCredentialsPage.Default.DefaultPassword, Runtime.EncryptionKey);
}
}
else
{
_rdpClient.AdvancedSettings2.ClearTextPassword = password;
}
}
else
{
_rdpClient.AdvancedSettings2.ClearTextPassword = password;
}
if (string.IsNullOrEmpty(domain))

View File

@@ -1114,10 +1114,10 @@ If you run into such an error, please create a new connection file!</value>
<value>Use the Credential Security Support Provider (CredSSP) for authentication if it is available.</value>
</data>
<data name="PropertyDescriptionUseRestrictedAdmin" xml:space="preserve">
<value>Use restricted admin mode on the target host (local system context). Credentials are not forwarded to the remote host; the current user's Kerberos ticket is used instead. Recommended for AD Protected Users accounts where NTLM authentication is disabled. Requires the connecting user to have administrative rights on the target.</value>
<value>Use restricted admin mode on the target host (local system context).</value>
</data>
<data name="PropertyDescriptionUseRCG" xml:space="preserve">
<value>Use Remote Credential Guard to tunnel authentication on target back to source through the RDP channel. Kerberos requests are redirected back to the connecting device, so credentials are never sent to the remote host. Recommended for AD Protected Users accounts where NTLM authentication is disabled. Requires both client and server to be domain-joined.</value>
<value>Use Remote Credential Guard to tunnel authentication on target back to source through the RDP channel.</value>
</data>
<data name="PropertyDescriptionUser1" xml:space="preserve">
<value>Feel free to enter any information you need here.</value>

View File

@@ -204,6 +204,11 @@ namespace mRemoteNG.UI.Menu
private static void OpenUrl(string url)
{
if (string.IsNullOrWhiteSpace(url) ||
(!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)))
return;
var startInfo = new ProcessStartInfo
{
FileName = url,

View File

@@ -99,6 +99,13 @@ namespace mRemoteNG.UI.Window
return;
}
// Only allow http/https URLs to prevent exploitation via custom URI schemes
if (!linkUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) &&
!linkUri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase))
{
return;
}
var startInfo = new ProcessStartInfo
{
FileName = linkUri.ToString(),