-
Notifications
You must be signed in to change notification settings - Fork 10
[temp] to compare with pr #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* build scripts * update README * default implementation for 'freerdp_channels_load_static_addin_entry' (bug in freerdp build when disable channels) Changes not added: * /libfreerdp/core/transport.c (???) * /libfreerdp\core\proxy.c (can be set from outside: settings->ProxyType = PROXY_TYPE_IGNORE;) * /winpr\libwinpr\utils\debug.c (seems to be fixed) * /winpr/include/winpr/nt.h (fixed)
* nogui free rdp client (nuget package)
(when src ==dst)
This reverts commit 0620e21.
This reverts commit de12039.
* Add customport option * don't check colordepth for session as it may be negotiated or smth
* fwd freerdp logs to logging * fwd runid from Activity * add freerdp logs filter * arrange * filters update long fire place video * remove activity support for runid * filter logging and arrange code * remove debug except ....nego * revert tests * Revert "revert tests" This reverts commit b5dcac9. * adjust filter * Revert "Revert "revert tests"" This reverts commit 1447abd. * update logs filter * TryAcquireInitLock and rearrange to use DI * review
- modify the CI to publish the NuGet package - write tests - centralize NuGet package reference via MSBuild
* - stop using Marshal.PtrToStructure - write local test * add test for non-enum structs
* add loggong tests * update logging filter for order falgs * ensure tests do not run in parallel * remove the need for host to configure logs forwarding * check for nulls on input
make it predictable
… about the need for manually recording the current TAG and HASH from the offical FreeRDP repo - install the `Microsoft.SourceLink.GitHub` NuGet in all CSPROJs so that we'll get the current Git hash appended to AssemblyInformationalVersionAttribute
- drop the TFM's "windows" constraint - add the admin parameter to the EnsureUserIsSetUp method - stop adding created users to "Remote Desktop Users"
- create an helper method for the 8 cases where we create RdpConnectionSettings from UserExistsDetail
* FreeRDP updates - copied branch "uipath" and rebased onto tag "2.11.2" - bumped OpenSSL to tag "openssl-3.0.12" - fixed breaks: - updated linker deps in FreeRdpWrapper for both Debug and Release - build openssl with no dynamic legacy modules - build freerdp with channels (wfreerdp.exe didn't work without channels) - ProcessRunner simplification - Increase DefaultTimeout to 2 minutes (on CI some tine "netsh" coomand takes more than 30 seconds)
Bump version to 23.12
… the final message pretty
Error handling: Make error message pretty
* commission separate list of prefixes for filtering original warnings * unit test
[ROBO-3413] fix rdp license leak
…tes (#38) Usernames containing these character would lead to command errors when being parsed, they have been surrounded by double quotes where possible or explicit handling has been added. Co-authored-by: Daniel Stanciu <daniel.stanciu@uipath.com>
#39) * Add optional callback that's called when FreeRDP session disconnects ROBO-3822
…OBO-4059 (#40) * Create git tag when publishing package Added option to create a tag with the same name as the published package. The tag is only created if a package was also published successfully. * Set version suffix based on branch + only create tag from uipath branch
* [ROBO-4715] fix pipeline enforcing msvc version https://uipath.atlassian.net/browse/ROBO-4715
| name: Analyze | ||
| runs-on: ubuntu-latest | ||
|
|
||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| language: [ 'cpp' ] | ||
| # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] | ||
| # Learn more: | ||
| # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v2 | ||
|
|
||
| # Initializes the CodeQL tools for scanning. | ||
| - name: Initialize CodeQL | ||
| uses: github/codeql-action/init@v1 | ||
| with: | ||
| languages: ${{ matrix.language }} | ||
| # If you wish to specify custom queries, you can do so here or in a config file. | ||
| # By default, queries listed here will override any specified in a config file. | ||
| # Prefix the list here with "+" to use these queries and those in the config file. | ||
| # queries: ./path/to/local/query, your-org/your-repo/queries@main | ||
|
|
||
| # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). | ||
| # If this step fails, then you should remove it and run the build manually (see below) | ||
| # - name: Autobuild | ||
| # uses: github/codeql-action/autobuild@v1 | ||
|
|
||
| # ℹ️ Command-line programs to run using the OS shell. | ||
| # 📚 https://git.io/JvXDl | ||
|
|
||
| # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines | ||
| # and modify them (or add more) to build your code if your project | ||
| # uses a compiled language | ||
|
|
||
| - run: | | ||
| sudo apt update | ||
| sudo apt install libxrandr-dev libxinerama-dev libusb-1.0-0-dev xserver-xorg-dev libswscale-dev libswresample-dev libavutil-dev libavcodec-dev libcups2-dev libpulse-dev libasound2-dev libpcsclite-dev xsltproc libxcb-cursor-dev libxcursor-dev libcairo2-dev libfaac-dev libfaad-dev libjpeg-dev libgsm1-dev ninja-build libxfixes-dev libxkbcommon-dev libwayland-dev libpam0g-dev libxdamage-dev libxcb-damage0-dev ccache libxtst-dev libfuse-dev libsystemd-dev libcairo2-dev libsoxr-dev | ||
| mkdir ci-build | ||
| cd ci-build | ||
| cmake -GNinja ../ci/cmake-preloads/config-linux-all.txt .. | ||
| cmake --build . | ||
|
|
||
| - name: Perform CodeQL Analysis | ||
| uses: github/codeql-action/analyze@v1 |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To fix this issue, the permissions key should be added to the job or to the top level of the workflow file to explicitly specify the minimum required permissions for running the workflow. The minimal necessary permissions for most CodeQL-only analysis workflows are contents: read (enough to read the repository contents and run analysis, not enough to write changes or interact elsewhere). This should be inserted either at the root level, or directly under the job that requires it; in this case, following the flagged issue on line 25, the block should be added under the analyze job in the .github/workflows/codeql-analysis.yml file. No new imports, methods, or other variable changes are required.
-
Copy modified lines R27-R28
| @@ -24,6 +24,8 @@ | ||
| analyze: | ||
| name: Analyze | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
|
|
||
| strategy: | ||
| fail-fast: false |
| process.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); | ||
|
|
||
| _ = process.Start(); | ||
| _logger?.LogRunStarted(startInfo.FileName, startInfo.Arguments); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to field _password : String
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
How to, in general terms, fix the problem:
Avoid logging sensitive information such as passwords in cleartext. When logging command invocations or arguments that potentially contain sensitive information, the password should be redacted, masked, or replaced with a safe placeholder before logging. This can be done by parsing and removing/replacing the sensitive portion in any logged string, based on knowledge of which commands/parameters may include it.
Best way to fix without changing existing functionality:
- In
ProcessRunner.Run, ensure that logging methods (LogRunStarted,LogRunWaitCanceled,LogRunSucceeded,LogRunFailed) do not receive sensitive values unredacted in theargumentsfield. - Implement a logic to redact passwords in commands known to include literal passwords, such as when calling
net user ... [password] ...or similar commands as seen in the data flow. - Add a utility method in
ProcessRunnerto identify and mask passwords in command arguments (e.g., replace password with"****"when logging). - Use the redacted command arguments in all logger invocations within this method.
What is needed:
- A static method or private helper in
ProcessRunnerto redact passwords from argument strings based on the command (likely a regular expression fornet user ... [password]). - Use this helper to create a redacted version of
startInfo.Argumentsfor all logger calls. - There is no need for third-party dependencies—.NET regexes are sufficient.
- No changes to the business logic of how arguments are passed to the process: the actual command launched is unchanged; only logs are sanitized.
Files/lines to change:
- In
UiPath.FreeRdpClient/UiPath.SessionTools/Processes/ProcessRunner.cs, update every placestartInfo.Argumentsis passed to_logger?.Log*withinRun. - Add the redaction helper as a private static method to
ProcessRunner.
-
Copy modified line R4 -
Copy modified lines R43-R45 -
Copy modified line R54 -
Copy modified line R61 -
Copy modified line R67 -
Copy modified line R69 -
Copy modified line R73 -
Copy modified lines R77-R102
| @@ -1,7 +1,7 @@ | ||
| using Microsoft.Extensions.Logging; | ||
| using System.Diagnostics; | ||
| using System.Text; | ||
|
|
||
| using System.Text.RegularExpressions; | ||
| namespace UiPath.SessionTools; | ||
|
|
||
| using static Logging; | ||
| @@ -39,8 +39,10 @@ | ||
| process.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); | ||
|
|
||
| _ = process.Start(); | ||
| _logger?.LogRunStarted(startInfo.FileName, startInfo.Arguments); | ||
|
|
||
| var redactedArguments = RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments); | ||
| _logger?.LogRunStarted(startInfo.FileName, redactedArguments); | ||
|
|
||
| process.BeginOutputReadLine(); | ||
| process.BeginErrorReadLine(); | ||
|
|
||
| @@ -50,25 +51,26 @@ | ||
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, redactedArguments, stdout.ToString(), stderr.ToString()); | ||
|
|
||
| throw; | ||
| } | ||
|
|
||
| if (process.ExitCode is 0) | ||
| { | ||
| _logger?.LogRunSucceeded(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunSucceeded(startInfo.FileName, redactedArguments, stdout.ToString(), stderr.ToString()); | ||
| return (stdout.ToString(), process.ExitCode); | ||
| } | ||
|
|
||
| string strStdout = stdout.ToString(); | ||
| string strStderr = stderr.ToString(); | ||
| _logger?.LogRunFailed(startInfo.FileName, startInfo.Arguments, process.ExitCode, strStdout, strStderr); | ||
| _logger?.LogRunFailed(startInfo.FileName, redactedArguments, process.ExitCode, strStdout, strStderr); | ||
|
|
||
|
|
||
| if (throwOnNonZero) | ||
| { | ||
| throw new NonZeroExitCodeException(process.ExitCode, strStdout, strStderr, | ||
| FormatRunFailed(startInfo.FileName, startInfo.Arguments, $"{process.ExitCode}", strStdout, strStderr)); | ||
| FormatRunFailed(startInfo.FileName, redactedArguments, $"{process.ExitCode}", strStdout, strStderr)); | ||
| } | ||
|
|
||
| return (strStdout, process.ExitCode); | ||
| @@ -87,4 +74,30 @@ | ||
| Error = error; | ||
| } | ||
| } | ||
|
|
||
| // Redacts potential passwords from command arguments for logging purposes | ||
| private static string RedactSensitiveArguments(string fileName, string arguments) | ||
| { | ||
| if (string.Equals(fileName, "net", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| // net user "User" password, or net user "User" password /add | ||
| // Match: user "something" <password>... | ||
| // Do not redact /active, /expires, or similar, only redact the 3rd word! | ||
| // Regex: user\s+"[^"]+"\s+(\S+) | ||
| return Regex.Replace( | ||
| arguments, | ||
| @"(user\s+""[^""]+""\s+)(\S+)", | ||
| m => | ||
| { | ||
| // Don't redact if the parameter is a switch (starts with /) | ||
| // For "net user \"user\" /active", 2nd group is "/active" | ||
| if (m.Groups.Count > 2 && !m.Groups[2].Value.StartsWith("/")) | ||
| return m.Groups[1].Value + "****"; | ||
| return m.Value; | ||
| } | ||
| ); | ||
| } | ||
| // Optionally handle other commands as needed, e.g., wmic or custom scripts | ||
| return arguments; | ||
| } | ||
| } |
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to field _password : String
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To prevent accidental storage of sensitive information, especially passwords, in clear text logs, the logging statements that include startInfo.Arguments need to be sanitized before being logged.
- The affected regions are wherever
_logger?.LogRunWaitCanceled,_logger?.LogRunStarted,_logger?.LogRunFailed, and_logger?.LogRunSucceededare called, passingstartInfo.Arguments. - The recommended fix is to mask any sensitive information in
startInfo.Argumentsbefore logging it. For the currently known use case (thenet user ... password ...command), password values are space-delimited in the arguments. We can implement a utility method that scans command lines for likely passwords and replaces them with a mask (e.g.,*****). - Specifically:
- Add a method
SanitizeArgumentsForLogging(string arguments)that detects and masks passwords in command strings; call this method when passingstartInfo.Argumentsas a log parameter. - Only edit code within
ProcessRunner.csas that's where the logging happens. - Ensure the masking function is straightforward, deterministic, and does not break normal logging for non-sensitive usages.
- Add a method
-
Copy modified line R4 -
Copy modified lines R43-R44 -
Copy modified line R55 -
Copy modified line R62 -
Copy modified line R68 -
Copy modified line R73 -
Copy modified lines R77-R124
| @@ -1,6 +1,7 @@ | ||
| using Microsoft.Extensions.Logging; | ||
| using System.Diagnostics; | ||
| using System.Text; | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace UiPath.SessionTools; | ||
|
|
||
| @@ -39,7 +40,8 @@ | ||
| process.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); | ||
|
|
||
| _ = process.Start(); | ||
| _logger?.LogRunStarted(startInfo.FileName, startInfo.Arguments); | ||
| var sanitizedArgs = SanitizeArgumentsForLogging(startInfo.Arguments); | ||
| _logger?.LogRunStarted(startInfo.FileName, sanitizedArgs); | ||
|
|
||
| process.BeginOutputReadLine(); | ||
| process.BeginErrorReadLine(); | ||
| @@ -50,25 +52,25 @@ | ||
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, sanitizedArgs, stdout.ToString(), stderr.ToString()); | ||
|
|
||
| throw; | ||
| } | ||
|
|
||
| if (process.ExitCode is 0) | ||
| { | ||
| _logger?.LogRunSucceeded(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunSucceeded(startInfo.FileName, sanitizedArgs, stdout.ToString(), stderr.ToString()); | ||
| return (stdout.ToString(), process.ExitCode); | ||
| } | ||
|
|
||
| string strStdout = stdout.ToString(); | ||
| string strStderr = stderr.ToString(); | ||
| _logger?.LogRunFailed(startInfo.FileName, startInfo.Arguments, process.ExitCode, strStdout, strStderr); | ||
| _logger?.LogRunFailed(startInfo.FileName, sanitizedArgs, process.ExitCode, strStdout, strStderr); | ||
|
|
||
| if (throwOnNonZero) | ||
| { | ||
| throw new NonZeroExitCodeException(process.ExitCode, strStdout, strStderr, | ||
| FormatRunFailed(startInfo.FileName, startInfo.Arguments, $"{process.ExitCode}", strStdout, strStderr)); | ||
| FormatRunFailed(startInfo.FileName, sanitizedArgs, $"{process.ExitCode}", strStdout, strStderr)); | ||
| } | ||
|
|
||
| return (strStdout, process.ExitCode); | ||
| @@ -87,4 +74,52 @@ | ||
| Error = error; | ||
| } | ||
| } | ||
| /// <summary> | ||
| /// Masks passwords embedded in command line arguments for logging. | ||
| /// For lines of the form: net user "username" password | ||
| /// (and variations) it will replace the password only. | ||
| /// </summary> | ||
| private static string SanitizeArgumentsForLogging(string arguments) | ||
| { | ||
| // Simple heuristic for "net user" with password: mask third argument if present | ||
| // e.g., user "user" password | ||
| if (string.IsNullOrWhiteSpace(arguments)) | ||
| return arguments; | ||
|
|
||
| // Tokenize spaced args, but preserve quoted segments (naive splitting for simple cases) | ||
| var tokens = new List<string>(); | ||
| var current = new StringBuilder(); | ||
| bool inQuotes = false; | ||
| for (int i = 0; i < arguments.Length; i++) | ||
| { | ||
| var c = arguments[i]; | ||
| if (c == '"') inQuotes = !inQuotes; | ||
| if (!inQuotes && c == ' ') | ||
| { | ||
| if (current.Length > 0) | ||
| { | ||
| tokens.Add(current.ToString()); | ||
| current.Clear(); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| current.Append(c); | ||
| } | ||
| } | ||
| if (current.Length > 0) | ||
| tokens.Add(current.ToString()); | ||
|
|
||
| // For "user", third token is the password (net user "name" password ...) or (net user "name" password /add) | ||
| // For "localgroup", no password. For most others, password not public. | ||
| if (tokens.Count >= 3 && tokens[0].Equals("user", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| // Only mask if third token does not look like a switch (starts with '/') | ||
| if (!tokens[2].StartsWith("/")) | ||
| tokens[2] = "*****"; | ||
| } | ||
|
|
||
| // Reconstruct arguments | ||
| return string.Join(" ", tokens); | ||
| } | ||
| } |
|
|
||
| if (process.ExitCode is 0) | ||
| { | ||
| _logger?.LogRunSucceeded(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to field _password : String
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
To remediate this issue, we need to ensure that sensitive information—specifically passwords included in command arguments—is not written in cleartext to logs. The fix entails redacting passwords from the arguments string before passing it to any logging functions. This can be achieved by creating and using a helper method that detects password parameters in the command arguments and redacts their value, replacing them with a placeholder (e.g., "*****"). This method should be applied whenever process arguments are logged (e.g., in calls to _logger?.LogRunStarted(...), _logger?.LogRunSucceeded(...), _logger?.LogRunFailed(...), and _logger?.LogRunWaitCanceled(...)). Only the logged value should be redacted; the value used to execute the process must remain unmodified so functionality is unchanged.
Concretely:
- Add a method to redact password values from argument strings.
- Use this method to sanitize
startInfo.Argumentsbefore logging, e.g.,RedactSensitiveArguments(startInfo.Arguments). - Update all logger invocations in
ProcessRunner.Run(lines 42, 53, 60, 66) to use the redacted version.
Depending on the exact command grammar, basic redaction could, for example, replace value after a flag or positional password. For demonstration, we'll apply a simple regular expression to mask sequences that look like passwords in the common command constructions shown.
-
Copy modified line R8 -
Copy modified lines R19-R33 -
Copy modified lines R58-R59 -
Copy modified line R70 -
Copy modified line R77 -
Copy modified line R83
| @@ -5,6 +5,7 @@ | ||
| namespace UiPath.SessionTools; | ||
|
|
||
| using static Logging; | ||
| using System.Text.RegularExpressions; | ||
|
|
||
| public partial class ProcessRunner | ||
| { | ||
| @@ -15,6 +16,21 @@ | ||
| _logger = logger; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Redacts sensitive arguments (like passwords) from a process argument string. | ||
| /// Very basic implementation for "net user ... [password]" and similar formats. | ||
| /// </summary> | ||
| private static string RedactSensitiveArguments(string arguments) | ||
| { | ||
| // Mask password argument for commands like: net user "username" password | ||
| // This replaces any argument after 'user "..."' as password with "*****" | ||
| // Adjust this if your command grammar varies! | ||
| var userPwdPattern = @"(user\s+""[^""]+""\s+)(\S+)"; | ||
| arguments = Regex.Replace(arguments, userPwdPattern, "$1*****"); | ||
| // Optionally, extend to /password:xxx switches or other schemes as needed. | ||
| return arguments; | ||
| } | ||
|
|
||
| public virtual async Task<(string output, int exitCode)> Run(string fileName, string arguments, string workingDirectory = "", bool throwOnNonZero = false, CancellationToken ct = default) | ||
| { | ||
| var startInfo = new ProcessStartInfo() | ||
| @@ -39,7 +55,8 @@ | ||
| process.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); | ||
|
|
||
| _ = process.Start(); | ||
| _logger?.LogRunStarted(startInfo.FileName, startInfo.Arguments); | ||
| var redactedArgs = RedactSensitiveArguments(startInfo.Arguments); | ||
| _logger?.LogRunStarted(startInfo.FileName, redactedArgs); | ||
|
|
||
| process.BeginOutputReadLine(); | ||
| process.BeginErrorReadLine(); | ||
| @@ -50,20 +67,20 @@ | ||
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, redactedArgs, stdout.ToString(), stderr.ToString()); | ||
|
|
||
| throw; | ||
| } | ||
|
|
||
| if (process.ExitCode is 0) | ||
| { | ||
| _logger?.LogRunSucceeded(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunSucceeded(startInfo.FileName, redactedArgs, stdout.ToString(), stderr.ToString()); | ||
| return (stdout.ToString(), process.ExitCode); | ||
| } | ||
|
|
||
| string strStdout = stdout.ToString(); | ||
| string strStderr = stderr.ToString(); | ||
| _logger?.LogRunFailed(startInfo.FileName, startInfo.Arguments, process.ExitCode, strStdout, strStderr); | ||
| _logger?.LogRunFailed(startInfo.FileName, redactedArgs, process.ExitCode, strStdout, strStderr); | ||
|
|
||
| if (throwOnNonZero) | ||
| { |
|
|
||
| string strStdout = stdout.ToString(); | ||
| string strStderr = stderr.ToString(); | ||
| _logger?.LogRunFailed(startInfo.FileName, startInfo.Arguments, process.ExitCode, strStdout, strStderr); |
Check failure
Code scanning / CodeQL
Clear text storage of sensitive information High
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to parameter password : String
This stores sensitive data returned by
access to field _password : String
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
Generally, to remediate "clear text storage of sensitive information", we should avoid logging secret values. In this context, the arguments field constructed for process invocation may contain passwords in clear text (notably for commands like net user ... password), but logging infrastructure currently logs the entire arguments string.
A robust fix is to sanitize or redact sensitive information (such as passwords) before logging. This means masking or removing any passwords from arguments before passing it to the logger. A helper function should be added to redact passwords from such parameter strings. This helper can use a regular expression or simple text replacement to replace passwords in "net user" commands by replacing the password argument with a constant value like "REDACTED". All logging calls using startInfo.Arguments should instead use a sanitized version (e.g., RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments)).
This requires:
- Adding a method, e.g.,
RedactSensitiveArguments(string fileName, string arguments), to perform redaction. - Replacing all logger calls that use
startInfo.Argumentswith sanitized arguments. - Importing
System.Text.RegularExpressionsfor regex if needed.
All changes should be performed in UiPath.FreeRdpClient/UiPath.SessionTools/Processes/ProcessRunner.cs, as that is where the logging (and the original problem) occurs.
-
Copy modified line R4 -
Copy modified lines R13-R35 -
Copy modified line R65 -
Copy modified line R76 -
Copy modified line R83 -
Copy modified line R89
| @@ -1,7 +1,7 @@ | ||
| using Microsoft.Extensions.Logging; | ||
| using System.Diagnostics; | ||
| using System.Text; | ||
|
|
||
| using System.Text.RegularExpressions; | ||
| namespace UiPath.SessionTools; | ||
|
|
||
| using static Logging; | ||
| @@ -10,6 +10,29 @@ | ||
| { | ||
| private readonly ILogger? _logger; | ||
|
|
||
| /// <summary> | ||
| /// Redact sensitive data (such as passwords) from arguments before logging. | ||
| /// </summary> | ||
| private static string RedactSensitiveArguments(string fileName, string arguments) | ||
| { | ||
| // Only redact if the command is one we expect a password in. | ||
| // For "net user" commands: net user "user" password | ||
| if (string.Equals(fileName, "net", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| // regex to match: user "username" password [..] or user username password [...] | ||
| // Net user ADD: user "username" password /add | ||
| // Net user SET: user "username" password | ||
| // Replace password with *** | ||
| var netUserPattern = @"(user\s+""[^""]+""\s+)([^\s""]+)"; | ||
| arguments = Regex.Replace(arguments, netUserPattern, m => m.Groups[1].Value + "***REDACTED***", RegexOptions.IgnoreCase); | ||
|
|
||
| // Also handle user username password without quotes | ||
| netUserPattern = @"(user\s+[^\s""]+\s+)([^\s""]+)"; | ||
| arguments = Regex.Replace(arguments, netUserPattern, m => m.Groups[1].Value + "***REDACTED***", RegexOptions.IgnoreCase); | ||
| } | ||
| // For "wmic useraccount ... set PasswordExpires=false" there is no password, so nothing to redact. | ||
| return arguments; | ||
| } | ||
| public ProcessRunner(ILogger? logger = null) | ||
| { | ||
| _logger = logger; | ||
| @@ -39,7 +62,7 @@ | ||
| process.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); | ||
|
|
||
| _ = process.Start(); | ||
| _logger?.LogRunStarted(startInfo.FileName, startInfo.Arguments); | ||
| _logger?.LogRunStarted(startInfo.FileName, RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments)); | ||
|
|
||
| process.BeginOutputReadLine(); | ||
| process.BeginErrorReadLine(); | ||
| @@ -50,20 +73,20 @@ | ||
| } | ||
| catch (OperationCanceledException) | ||
| { | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunWaitCanceled(startInfo.FileName, RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments), stdout.ToString(), stderr.ToString()); | ||
|
|
||
| throw; | ||
| } | ||
|
|
||
| if (process.ExitCode is 0) | ||
| { | ||
| _logger?.LogRunSucceeded(startInfo.FileName, startInfo.Arguments, stdout.ToString(), stderr.ToString()); | ||
| _logger?.LogRunSucceeded(startInfo.FileName, RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments), stdout.ToString(), stderr.ToString()); | ||
| return (stdout.ToString(), process.ExitCode); | ||
| } | ||
|
|
||
| string strStdout = stdout.ToString(); | ||
| string strStderr = stderr.ToString(); | ||
| _logger?.LogRunFailed(startInfo.FileName, startInfo.Arguments, process.ExitCode, strStdout, strStderr); | ||
| _logger?.LogRunFailed(startInfo.FileName, RedactSensitiveArguments(startInfo.FileName, startInfo.Arguments), process.ExitCode, strStdout, strStderr); | ||
|
|
||
| if (throwOnNonZero) | ||
| { |
| winpr_RC4_Free(rdp->rc4_encrypt_key); | ||
| rdp->rc4_encrypt_key = NULL; | ||
| } | ||
| rdp_free_rc4_decrypt_keys(rdp); |
Check failure
Code scanning / CodeQL
Use of a broken or risky cryptographic algorithm High
call to rdp_free_rc4_decrypt_keys
This file makes use of a broken or weak cryptographic algorithm (specified by
call to winpr_RC4_New
This file makes use of a broken or weak cryptographic algorithm (specified by
call to rdp_free_rc4_encrypt_keys
This file makes use of a broken or weak cryptographic algorithm (specified by
call to winpr_RC4_New
This file makes use of a broken or weak cryptographic algorithm (specified by
call to rdp_free_rc4_decrypt_keys
This file makes use of a broken or weak cryptographic algorithm (specified by
call to rdp_free_rc4_encrypt_keys
This file makes use of a broken or weak cryptographic algorithm (specified by
call to rdp_free_rc4_decrypt_keys
This file makes use of a broken or weak cryptographic algorithm (specified by
call to rdp_free_rc4_encrypt_keys
|
|
||
| for (x = 0; x < ctx->pos; x++) | ||
| { | ||
| char* msg = str + ctx->pos * sizeof(char*) + x * UNWIND_MAX_LINE_SIZE; |
Check failure
Code scanning / CodeQL
Suspicious add with sizeof High
char **
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 4 months ago
The problem is on line 113, where pointer arithmetic is performed on a char**, which automatically scales by sizeof(char*), but the code multiplies the offset by an additional sizeof(char*), effectively causing a miscalculation. The intention seems to be to compute a pointer to a buffer region after the array of pointers. This should be done by first casting the pointer to a char*, so arithmetic operates in bytes. The correct way is:
- Calculate the base address for the buffer portion by taking the start address:
(char*)str + ctx->pos * sizeof(char*) - Add the offset for the current message:
x * UNWIND_MAX_LINE_SIZE
So, the fixed line is:
char* msg = ((char*)str) + ctx->pos * sizeof(char*) + x * UNWIND_MAX_LINE_SIZE;Only line 113 needs this fix, with no extra includes or definitions.
-
Copy modified line R113
| @@ -110,7 +110,7 @@ | ||
|
|
||
| for (x = 0; x < ctx->pos; x++) | ||
| { | ||
| char* msg = str + ctx->pos * sizeof(char*) + x * UNWIND_MAX_LINE_SIZE; | ||
| char* msg = ((char*)str) + ctx->pos * sizeof(char*) + x * UNWIND_MAX_LINE_SIZE; | ||
| const unwind_info_t* info = &ctx->info[x]; | ||
| Dl_info dlinfo = { 0 }; | ||
| int rc = dladdr(info->pc, &dlinfo); |
This is how are pull requests handled by FreeRDP
Preparations before creating a pull
.clang-formatclangformatreformats the whole codebaseTo ease accepting your contribution
What you should be prepared for
Please remove this text before submitting your pull!