-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Fix various problems with install path and app path variables #968
Conversation
If there is no hard-coded UI helper, we should gracefully handle the lookup by returning false, rather than crashing due to a argument exception when passing `null` or an empty string to a Path API.
Ensure that we don't return empty `PATH` values on Windows when splitting. It's common that on Windows the `PATH` can be inadvertently modified such that an empty value is included, and this can lead to weird resolution of executables using the current directory. As it stands, no existing codepaths would trigger this today when invoked by Git for Windows, but let's make sure this never happens in the future by mistake!
On Windows, when invoked as a partial name (e.g., `manager`) our command line argv[0] is just a file name, not a full file path! We incorrectly assumed that `Environment.GetCommandLineArgs()[0]` was always absolute! We should instead use `AppContext.BaseDirectory` that, in all circumstances tested, all on TFMs and OSs, all publish options, and as a .NET tool... returns the expected full, absolute path to the installation directory.
This comment was marked as off-topic.
This comment was marked as off-topic.
This is great, thank you! The explanation why this cannot be triggered (at least in the common scenarios) is that Git calls the credential helper via the shell: https://github.com/git/git/blob/v2.38.1/credential.c#L282. And thanks to using a Bash in Git for Windows that relies on the MSYS2 runtime, this means that empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work. Thank you!
// Ensure we don't return empty values here - callers may use this as the base | ||
// path for `Path.Combine(..)`, for which an empty value means 'current directory'. | ||
// We only ever want to use the current directory for path resolution explicitly. | ||
return value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is so much easier than what I would have done. 👍
@@ -91,7 +91,7 @@ public static string GetEntryApplicationPath() | |||
|
|||
public static string GetInstallationDirectory() | |||
{ | |||
return Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); | |||
return AppContext.BaseDirectory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is fantastic that you tested all those scenarios and wrote about it in the commit message. Otherwise I would have had concerns that this break things left and right. But that testing builds confidence in the correctness of this change!
Fix a bug in the old-name warning detection that only presents on Windows when bundled with Git for Windows, and when configured using the shorthand config `credential.helper=manager-core`. In this scenario, our argv[0] is missing the ".exe" extension (that's actually present in the file name of course) because ... mingw reasons. Instead of matching "git-credential-manager-core.exe" on Windows, just strip ".exe" if present on Windows, and always match "git-credential-manager-core" on all platforms.
Fix another bug in how we compute the Application Executable path on Windows. It some cases we can still get a relative/non-absolute path to the entry executable. If we get a filename/non-path from the native API calls then return null and fallback to using process/module image resolution instead. For .NET Framework on Windows, this is OK. We will want to revisit this on .NET (Core) on Windows, if and when we get around to that...
f7ec78b
to
b848716
Compare
// Trim any (.exe) file extension if we're on Windows | ||
// Note that in some circumstances (like being called by Git when config is set | ||
// to just `helper = manager-core`) we don't always have ".exe" at the end. | ||
if (PlatformUtils.IsWindows() && appPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about ignoring the case here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great finds and fixes. The amount of detail in your commit messages/description made this a very easy change to review.
return argv0; | ||
|
||
// If this isn't absolute then we should return null to prevent any | ||
// caller that expect only an absolute path from mis-using this result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// caller that expect only an absolute path from mis-using this result. | |
// caller that expects only an absolute path from mis-using this result. |
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When looking up an executable via the `_which` function, Git GUI imitates the `execlp()` strategy where the environment variable `PATH` is interpreted as a list of paths in which to search. For historical reasons, stemming from the olden times when it was uncommon to download a lot of files from the internet into the current directory, empty elements in this list are treated as if the current directory had been specified. Nowadays, of course, this treatment is highly dangerous as the current directory often contains files that have just been downloaded and not yet been inspected by the user. Unix/Linux users are essentially expected to be very, very careful to simply not add empty `PATH` elements, i.e. not to make use of that feature. On Windows, however, it is quite common for `PATH` to contain empty elements by mistake, e.g. as an unintended left-over entry when an application was installed from the Windows Store and then uninstalled manually. While it would probably make most sense to safe-guard not only Windows users, it seems to be common practice to ignore these empty `PATH` elements _only_ on Windows, but not on other platforms. Sadly, this practice is followed inconsistently between different software projects, where projects with few, if any, Windows-based contributors tend to be less consistent or even "blissful" about it. Here is a non-exhaustive list: Cygwin: It specifically "eats" empty paths when converting path lists to POSIX: cygwin/cygwin@753702223c7d I.e. it follows the common practice. PowerShell: It specifically ignores empty paths when searching the `PATH`. The reason for this is apparently so self-evident that it is not even mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables#path-information I.e. it follows the common practice. CMD: Oh my, CMD. Let's just forget about it, nobody in their right (security) mind takes CMD as inspiration. It is so unsafe by default that we even planned on dropping `Git CMD` from Git for Windows altogether, and only walked back on that plan when we found a super ugly hack, just to keep Git's users secure by default: git-for-windows/MINGW-packages@82172388bb51 So CMD chooses to hide behind the battle cry "Works as Designed!" that all too often leaves users vulnerable. CMD is probably the most prominent project whose lead you want to avoid following in matters of security. Win32 API (`CreateProcess()`) Just like CMD, `CreateProcess()` adheres to the original design of the path lookup in the name of backward compatibility (see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw for details): If the file name does not contain a directory path, the system searches for the executable file in the following sequence: 1. The directory from which the application loaded. 2. The current directory for the parent process. [...] I.e. the Win32 API itself chooses backwards compatibility over users' safety. Git LFS: There have been not one, not two, but three security advisories about Git LFS executing executables from the current directory by mistake. As part of one of them, a change was introduced to stop treating empty `PATH` elements as equivalent to `.`: git-lfs/git-lfs@7cd7bb0a1f0d I.e. it follows the common practice. Go: Go does not follow the common practice, and you can think about that what you want: https://github.com/golang/go/blob/go1.19.3/src/os/exec/lp_windows.go#L114-L135 https://github.com/golang/go/blob/go1.19.3/src/path/filepath/path_windows.go#L108-L137 Git Credential Manager: It tries to imitate Git LFS, but unfortunately misses the empty `PATH` element handling. As of time of writing, this is in the process of being fixed: git-ecosystem/git-credential-manager#968 So now that we have established that it is a common practice to ignore empty `PATH` elements on Windows, let's assess this commit's change using Schneier's Five-Step Process (https://www.schneier.com/crypto-gram/archives/2002/0415.html#1): Step 1: What problem does it solve? It prevents an entire class of Remote Code Execution exploits via Git GUI's `Clone` functionality. Step 2: How well does it solve that problem? Very well. It prevents the attack vector of luring an unsuspecting victim into cloning an executable into the worktree root directory that Git GUI immediately executes. Step 3: What other security problems does it cause? Maybe non-security problems: If a project (ab-)uses the unsafe `PATH` lookup. That would not only be unsafe, though, but fragile in the first place because it would break when running in a subdirectory. Therefore I would consider this a scenario not worth keeping working. Step 4: What are the costs of this measure? Almost nil, except for the time writing up this commit message ;-) Step 5: Given the answers to steps two through four, is the security measure worth the costs? Yes. Keeping Git's users Secure By Default is worth it. It's a tiny price to pay compared to the damages even a single successful exploit can cost. So let's follow that common practice in Git GUI, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Fix several bugs in how we compute the app path and install dir on Windows.
In some cases we can still get a relative/non-absolute path to the entry executable. If we get a filename/non-path from the native API calls then return null and fallback to using process/module image resolution instead. For .NET Framework on Windows, this is OK. We will want to revisit this on .NET (Core) on Windows, if and when we get around to that...
Bug number two.. for the install dir, on Windows, when invoked as a partial name (e.g.,
manager
) our command line argv[0] is just a file name, not a full file path! We incorrectly assumed thatEnvironment.GetCommandLineArgs()[0]
was always absolute!We should instead use
AppContext.BaseDirectory
that, in all circumstances tested, all on TFMs and OSs, all publish options, and as a .NET tool... returns the expected full, absolute path to the installation directory.Bug number three is in the old-name warning detection that only presents on Windows when bundled with Git for Windows, and when configured using the shorthand config
credential.helper=manager-core
. In this scenario, our argv[0] is missing the ".exe" extension (that's actually present in the file name of course) because ... mingw reasons.Instead of matching "git-credential-manager-core.exe" on Windows, just strip ".exe" if present on Windows, and always match "git-credential-manager-core" on all platforms.
Whilst fixing these three bugs, I also spotted two other potential edge cases that should be fixed..
Ensure that we don't return empty
PATH
values on Windows when splitting. It's common that on Windows thePATH
can be inadvertently modified such that an empty value is included, and this can lead to weird resolution of executables using the current directory.Thanks for @dscho for spotting this possible issue! This sort of accidental "current directory" resolution is often a cause of security issues - after careful testing, this ends up not being possible to trigger, but we should guard for it explicitly to be safe in the future!
If there is no hard-coded UI helper, we should gracefully handle the lookup by returning false, rather than crashing due to a argument exception when passing
null
or an empty string to aSystem.IO.Path
API.