在C#中使用ProcessStartInfo定位dotnet.exe的完整路径
如何安全定位dotnet.exe的完整路径
要满足SonarCloud的安全要求,同时规避PATH注入风险,你可以按以下优先级逐步定位dotnet的完整路径:
优先读取
DOTNET_ROOT环境变量
尽管部分用户机器可能未配置这个变量,但它是官方定义的.NET安装根目录标识,存在时直接使用最可靠。拼接路径时注意区分操作系统:string? dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT"); if (!string.IsNullOrEmpty(dotnetRoot)) { string dotnetExePath = Path.Combine(dotnetRoot, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dotnet.exe" : "dotnet"); if (File.Exists(dotnetExePath)) { // 使用该路径执行dotnet } }检查系统标准安装路径
针对不同平台的默认安装位置做验证:- Windows:通过注册表获取官方安装路径
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // 先检查系统级安装 using var systemKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedHost"); string? systemPath = systemKey?.GetValue("Path") as string; if (!string.IsNullOrEmpty(systemPath) && File.Exists(systemPath)) { // 使用系统级安装路径 } // 可选:检查用户级安装(针对仅当前用户安装的.NET) using var userKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedHost"); string? userPath = userKey?.GetValue("Path") as string; if (!string.IsNullOrEmpty(userPath) && File.Exists(userPath)) { // 使用用户级安装路径 } } - Linux/macOS:验证标准安装目录
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { string[] standardPaths = { "/usr/share/dotnet/dotnet", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".dotnet/dotnet") }; foreach (string path in standardPaths) { if (File.Exists(path)) { // 使用该路径执行dotnet break; } } }
- Windows:通过注册表获取官方安装路径
安全调用系统工具获取路径
如果以上方法都无法定位,可通过指定where/which的完整系统路径来避免PATH注入风险,再用它们查找dotnet:string dotnetPath = string.Empty; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // 直接调用系统目录下的where.exe var processStartInfo = new ProcessStartInfo("C:\\Windows\\System32\\where.exe", "dotnet.exe") { RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(processStartInfo); process?.WaitForExit(); if (process?.ExitCode == 0) { string? output = process.StandardOutput.ReadLine(); if (!string.IsNullOrEmpty(output) && File.Exists(output)) { dotnetPath = output; } } } else { // 直接调用系统目录下的which var processStartInfo = new ProcessStartInfo("/usr/bin/which", "dotnet") { RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(processStartInfo); process?.WaitForExit(); if (process?.ExitCode == 0) { string? output = process.StandardOutput.ReadLine(); if (!string.IsNullOrEmpty(output) && File.Exists(output)) { dotnetPath = output; } } }
你提到的“若恶意人员已注入PATH中的dotnet,用户自身运行dotnet命令也会受影响”确实成立,但通过上述方式定位路径,能避免你的CLI工具成为攻击入口,同时满足静态代码分析的安全要求。
内容的提问来源于stack exchange,提问作者ThomasArdal
相关产品推荐
相关产品推荐

