Skip to content

Commit 9394c25

Browse files
authored
Merge branch 'master' into snyk-upgrade-d1dcb792734b382f8ffc70faf9e8ca8c
2 parents 6dfc93e + bbaccc7 commit 9394c25

27 files changed

+332
-111
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ Before creating one, please search https://github.com/gerardog/gsudo/issues?q=
2828
## Context:
2929
- Windows version:
3030
<!-- To get Windows version, press Win+R, type `winver` and press enter.
31-
For example: Win11 21H2 - Spanish ->
31+
For example: Win11 21H2 - Spanish -->
3232
- gsudo version:
3333
<!-- Run `gsudo -v` to get gsudo version -->

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ Here are the `Credentials Cache` Modes:
282282
- This is the default mode. (Use `gsudo config CacheMode Explicit` to revert to this value).
283283
- `Auto:` Similar to unix-sudo. The first elevation shows a UAC popup and **starts a cache session automatically**.
284284
- Run `gsudo config CacheMode Auto` to use this mode.
285-
- `Disabled:` Every elevation shows a UAC popup, and tryoing to start a cache session will throw an error..
285+
- `Disabled:` Every elevation shows a UAC popup, and trying to start a cache session will throw an error..
286286
- Run `gsudo config CacheMode Disabled` to use this mode.
287287

288288
In any case, you can stop all cache sessions with `gsudo -k`.

docs/docs/gsudo-vs-sudo.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
sidebar_position: 7
3+
title: Comparison with Microsoft sudo
4+
#hide_title: true
5+
---
6+
7+
# Comparison between gsudo and Microsoft sudo
8+
9+
`gsudo` was born in 2019 as a productivity tool and is open-source. It has been downloaded over 700k times so far and has enjoyed a warm reception from users.
10+
11+
Microsoft initially declined to create a similar tool, citing security concerns. However `gsudo`'s documentation [challenged this view](security.md) arguing that absolute security is unattainable without altering Windows itself, and that the default same-desktop UAC is not completely secure either.
12+
13+
In February 2024, Microsoft reversed its stance and released [Sudo for Windows](https://devblogs.microsoft.com/commandline/introducing-sudo-for-windows/).
14+
15+
Surprisingly, Microsoft's sudo does not leverage new OS features to enhance security. Its mechanisms are akin to `gsudo`, making their security models comparable. The question of which one is more secure depends on which version of each are you comparing, and how many open bugs it has. The initial release of Microsoft's sudo presented some [critical issues](https://www.tiraniddo.dev/2024/02/sudo-on-windows-quick-rundown.html) that they will hopefully address very soon. `gsudo` has fixed similar issues in the past and may in the future.
16+
17+
## Sudo Tools Feature Comparison
18+
19+
### Is it a proper Sudo tool?
20+
| Feature | `gsudo` | Sudo for Windows |
21+
| ------- | ------- | ------------------ |
22+
| Executes command with elevated permissions | Yes | Yes |
23+
| Supports output redirection (`sudo dir > file.txt`) | Yes | Yes |
24+
| Supports input redirection (`echo md folder \| sudo cmd`) | Yes | Partial (Only with output redirection) |
25+
| Returns the command exit code | Yes | No |
26+
| Source code available | [Yes](https://github.com/gerardog/gsudo) | Not for `sudo.exe`, but [promised](https://github.com/microsoft/sudo/blob/f8f1d05/README.md#contributing) |
27+
28+
### Security Impersonation Features
29+
30+
| Feature | `gsudo` | Sudo for Windows |
31+
| ------- | ------- | ------------------ |
32+
| Run with custom Integrity | Yes (`-i`, `--integrity`) | No |
33+
| Run as System | Yes (`-s`, `--system`) | No |
34+
| Run as TrustedInstaller | Yes (`--ti`)| No |
35+
| Run as user | Yes (`-u user`) | No |
36+
37+
### User Experience
38+
39+
| Feature | `gsudo` | Sudo for Windows |
40+
| ------- | ------- | ------------------ |
41+
| Easy to install and update | Yes (winget, choco, scoop) | No (Windows Insider build required) |
42+
| See less UAC Pop-ups | Yes ([Credentials Cache](credentials-cache.md)) | No |
43+
| Elevate current shell | Yes | No |
44+
| Elevate commands using current shell | Yes | No |
45+
| Red # indicator for elevation on CMD | Yes | No |
46+
47+
### Additional Features
48+
49+
| Feature | `gsudo` | Sudo for Windows |
50+
| ------- | ------- | ------------------ |
51+
| Run in new window | Yes | Yes |
52+
| Option to keep new window open until a key is pressed | [Yes](tips/elevation-in-new-window.md) | No |
53+
| Option to keep new window's shell open | [Yes](tips/elevation-in-new-window.md) | No |
54+
| Run with Input Disabled | [Yes](https://gerardog.github.io/gsudo/docs/security#what-are-the-risks-of-running-gsudo) | Yes |
55+
| Elevate last command with `sudo !!` | Yes | No |
56+
57+
### PowerShell
58+
59+
| Feature | `gsudo` | Sudo for Windows |
60+
| ------- | ------- | ------------------ |
61+
| Elevation syntax | `gsudo { Script } -args $a,$b` [syntax](usage/powershell.md#using-gsudo-scriptblock-syntax) | Unknown, possibly: `sudo pwsh { script }` |
62+
| Auto-complete of last 3 commands | Yes (with [gsudoModule](usage/powershell.md#gsudo-powershell-module)) | No |
63+
| Auto-complete of options | Yes (with [gsudoModule](usage/powershell.md#gsudo-powershell-module)) | No |
64+
| Red # indicator for elevation | Yes (with [gsudoModule](usage/powershell.md#gsudo-powershell-module)) | No |
65+
66+
## What if I install both?
67+
68+
If you have both Microsoft Sudo and `gsudo` installed, they both should work independently.
69+
70+
The `sudo` keyword will run Microsoft's sudo instead of `gsudo` because the typical install of `Sudo for Windows` (which is via a Windows Insider build) puts it in `c:\Windows\System32\sudo.exe`. This folder appears first in the `PATH` environment variable, therefore when running `sudo`, the Microsoft `sudo.exe` will take precedence over gsudo's `sudo` alias.

docs/docs/security.md

+17-13
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ title: Security Considerations
44
hide_title: true
55
---
66

7-
## Why Windows doesn't have a `sudo` command? Should it have one?
7+
## Why doesn't Windows have a `sudo` command? Should it have one?
88

99
To answer this question, we first have to take a look back at the history.
1010

1111
In August 2002, Chris Paget released a white paper describing a form of attack against event-driven systems that he termed Shatter Attack. It allowed processes in the same session to bypass security restrictions by abusing Windows Message loop.
1212

13-
Microsoft response was to add "User Interface Privilege Isolation" (UIPI) and the "User Access Control" (UAC) popup to the next major release: Windows Vista. Privileged processes would then run "elevated" at high integrity level, out of reach of processes at lower, non-admin, levels.
13+
Microsoft's response was to add "User Interface Privilege Isolation" (UIPI) and the "User Access Control" (UAC) popup to the next major release: Windows Vista. Privileged processes would then run "elevated" at high integrity level, out of reach of processes at lower, non-admin, levels.
1414

15-
I assume that at this point Microsoft decided not to make a `sudo` tool for windows. It would be an unwanted bridge between two worlds that intended to isolate.
15+
I assume that at this point, Microsoft decided not to make a `sudo` tool for windows. It would be an unwanted bridge between two worlds that intended to isolate.
1616

17-
But that insulation quickly proved weak. Let me [quote Raymond Chen from Microsoft](https://devblogs.microsoft.com/oldnewthing/20160816-00/?p=94105):
17+
However, that insulation quickly proved to be weak. Let me [quote Raymond Chen from Microsoft](https://devblogs.microsoft.com/oldnewthing/20160816-00/?p=94105):
1818

1919
> There’s a setting that lets you specify how often you want to be prompted by UAC. You can set any of four levels:
2020
>
@@ -28,40 +28,44 @@ But that insulation quickly proved weak. Let me [quote Raymond Chen from Microso
2828
> - Always notify
2929
> - Meh
3030
>
31-
> The reason why all the other options collapse into Meh is that the `Notify only when apps try to change settings` option can be subverted by any app simply by injecting a thread into (...)
31+
> The reason why all the other options collapse into Meh is that the `Notify only when apps try to change settings` option can be subverted by any app simply by injecting a thread (... a hacking technique explained ...)
3232
33-
And, up to this day, Windows 10 & 11, defaults to "Meh". Microsoft default is: user convenience at the expense of lesser security.
33+
And, up to this day, Windows 10 & 11, defaults corresponds to that "Meh". Microsoft's default stance is user convenience at the expense of lesser security.
3434

3535
---
3636
![Vista UAC](../static/img/Vista-UAC.png)
3737
[Windows 11 UAC Settings: Default mode is recommended only if you **don't** run untrusted software.]
3838

3939
---
4040

41-
Over time, no less than a hundred UAC-bypass techniques were disclosed. Many of them still work in an updated Windows 11. Windows Defender, or your antivirus of choice, will stop them (hopefully). But if you disable your AV, UAC bypass is easy.
41+
Over time, more than a hundred UAC-bypass techniques have been disclosed. Many of them still work in an updated Windows 11. It is Windows Defender, or your antivirus of choice, who may stop them (hopefully). But if you disable your AV, UAC bypass is easy.
4242

43-
Microsoft did not patch them. Instead, they assumed publicly that `UAC/UIPI` in default mode is not a security boundary. I will [quote Microsoft documentation](https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-user-account-control#:~:text=More%20important%2C%20Same%2Ddesktop%20Elevation,be%20considered%20a%20convenience%20feature.) :
43+
And Microsoft can't just patch them all without loosing 'convenience' features. They instead, they assumed publicly that `UAC/UIPI` in default mode is not a security boundary. I will [quote Microsoft documentation](https://docs.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-user-account-control#:~:text=More%20important%2C%20Same%2Ddesktop%20Elevation,be%20considered%20a%20convenience%20feature.) :
4444

4545
> Same-desktop Elevation in UAC isn't a security boundary. It can be hijacked by unprivileged software that runs on the same desktop. Same-desktop Elevation should be considered a convenience feature.
4646
47-
Which means: <b>UAC does not protect you from threats. It's a convenience tool that protects you from shooting yourself in the foot. </b>
47+
Which to me, it means: <b>UAC is a convenience tool. It does not protect you from threats, it works as a warning that protects you from shooting yourself in the foot.</b>
4848

49-
And, in my opinion, it's not doing the best possible job:
49+
And if UAC is a convenience tool, in my opinion it's not doing the best possible job:
5050

5151
- You waste important time by switching between elevated and unelevated windows. You must manually carry your command and context to the elevated window, each time, back and forth.
5252
- ... or you suffer from "elevation fatigue". For example, you elevate a whole console beforehand, and you do all your stuff there, likely running non-admin or untrusted stuff as admin.
5353

54-
**In conclusion:**
54+
**In conclusion:**
5555

56-
- Same-desktop UAC is a vulnerable convenience feature, and so is `gsudo`. In any case, **the only thing that protects you from malware is you and your Antivirus.**.
56+
- Same-desktop UAC is a vulnerable convenience feature.
57+
- `gsudo` is also a vulnerable convenience feature.
58+
- Whether you use `gsudo` or not, **the only thing that protects you from malware is not UAC, it is you and your Antivirus.**.
59+
60+
So, if you decide to use `gsudo`, here are the risks:
5761

5862
## What are the risks of running gsudo?
5963

6064
gsudo could be used as an attack vector for escalation of privileges. Using antivirus software and avoiding running untrusted software
6165

6266
- **Abusing an elevation made with gsudo:**
6367

64-
A medium integrity process could drive the gsudo-elevated process.
68+
A medium integrity process could drive the gsudo-elevated process.
6569

6670
When gsudo elevates **in the same console**, it creates a connection between a medium and a high integrity process. A malicious process (at medium integrity) can then drive the medium integrity console: sending keystrokes to the high integrity app, or scrapping its screen.
6771

docs/docs/troubleshooting.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 7
2+
sidebar_position: 10
33
hide_title: true
44
title: Troubleshooting
55
---

docs/docs/usage/powershell.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ When the current shell is `PowerShell`, gsudo can be used in the following ways:
2222
3. [`gsudo 'string command'`](#using-gsudo-command-syntax) => Old, legacy syntax.
2323

2424
- You can [add `gsudo` PowerShell Module](#powershell-profile-config) to your `$PROFILE`
25-
- This enables to use `gsudo !!` to elevate last command.
25+
- This allows tab-key auto-completition. For example, write 'gsudo` then `space` and then `tab` and your last executed command will be suggested.
26+
- Also enables to use `gsudo !!` to elevate last command.
2627

2728
- In a pipeline of commands, `gsudo` only elevates one command.
2829

docs/docusaurus.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const darkCodeTheme = require('prism-react-renderer/themes/dracula');
66

77
/** @type {import('@docusaurus/types').Config} */
88
const config = {
9-
title: 'gsudo (sudo for windows)',
9+
title: 'gsudo Documentation',
1010
tagline: 'The missing piece in Windows. Cherry-pick which commands to elevate with just one keyword.',
1111
url: 'https://gerardog.github.io',
1212
baseUrl: '/gsudo/',

docs/src/pages/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function HomepageHeader() {
1212
return (
1313
<header className={clsx('hero hero--primary', styles.heroBanner)}>
1414
<div className="container">
15-
<h1 className="hero__title">{siteConfig.title}</h1>
15+
<h1 className="hero__title">gsudo (sudo for Windows)</h1>
1616
<p className="hero__subtitle">{siteConfig.tagline}</p>
1717
<div className={styles.buttons}>
1818
<Link

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"dependencies": {
1717
"@docusaurus/core": "^2.4.1",
1818
"@docusaurus/plugin-google-gtag": "^2.4.3",
19-
"@docusaurus/plugin-sitemap": "^2.4.1",
19+
"@docusaurus/plugin-sitemap": "^2.4.3",
2020
"@docusaurus/preset-classic": "^2.4.1",
2121
"@mdx-js/react": "^1.6.22",
2222
"clsx": "^1.1.1",

src/gsudo.Wrappers.Tests/Invoke-gsudo.Tests.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Describe "PS Invoke-Gsudo (PSv$($PSVersionTable.PSVersion.Major))" {
4343
}
4444

4545
It "It throws with .Net Exceptions" {
46-
{ Invoke-gsudo { [int]::Parse('foo') } } | Should -throw "*Input string was not*"
46+
{ Invoke-gsudo { [int]::Parse('foo') } } | Should -throw "*nput string*"
4747
}
4848

4949
It "It throws when ErrorAction = Stop" {

src/gsudo.Wrappers/gsudo

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
# For better experience (fix credentials cache) in git-bash/MinGw create this wrapper can be added as function in .bashrc:
99
# gsudo() { WSLENV=WSL_DISTRO_NAME:USER:$WSLENV MSYS_NO_PATHCONV=1 gsudo.exe "$@"; }
1010

11-
WSLENV=WSL_DISTRO_NAME:USER:$WSLENV MSYS_NO_PATHCONV=1 "$( dirname -- "$0")/gsudo.exe" "$@"
11+
thisdir="$(dirname "$(readlink "$0")")"
12+
WSLENV=WSL_DISTRO_NAME:USER:$WSLENV MSYS_NO_PATHCONV=1 "${thisdir}/gsudo.exe" "$@"

src/gsudo/AppSettings/Settings.cs

+9-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Settings
8282

8383
public static RegistrySetting<string> ExceptionList { get; } =
8484
new RegistrySetting<string>(nameof(ExceptionList),
85-
defaultValue: "notepad.exe;powershell.exe;whoami.exe;",
85+
defaultValue: "notepad.exe;powershell.exe;whoami.exe;vim.exe;nano.exe;",
8686
deserializer: (string s)=>s,
8787
scope: RegistrySettingScope.GlobalOnly);
8888

@@ -127,8 +127,14 @@ internal static TimeSpan TimeSpanParseWithInfinite(string value)
127127
{
128128
if (value.In("-1", "Infinite"))
129129
return TimeSpan.MaxValue;
130-
else
131-
return TimeSpan.Parse(value, CultureInfo.InvariantCulture);
130+
131+
var timeSpan = TimeSpan.Parse(value, CultureInfo.InvariantCulture);
132+
133+
// Cap at 24 days.
134+
if (timeSpan.TotalDays > 24)
135+
return TimeSpan.MaxValue;
136+
137+
return timeSpan;
132138
}
133139

134140
internal static string TimeSpanWithInfiniteToString(TimeSpan value)

src/gsudo/Commands/RunCommand.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -231,15 +231,18 @@ private void AdjustUacIsolationRequest(ElevationRequest elevationRequest, bool i
231231
}
232232
}
233233

234-
internal static bool IsRunningAsDesiredUser()
234+
internal static bool IsRunningAsDesiredUser(bool allowHigherIntegrity = false)
235235
{
236236
if (InputArguments.TrustedInstaller && !WindowsIdentity.GetCurrent().Claims.Any(c => c.Value == Constants.TI_SID))
237237
return false;
238238

239239
if (InputArguments.RunAsSystem && !WindowsIdentity.GetCurrent().IsSystem)
240-
return false;
240+
return false;
241241

242-
if ((int)InputArguments.GetIntegrityLevel() != SecurityHelper.GetCurrentIntegrityLevel())
242+
if ((int)InputArguments.GetIntegrityLevel() != SecurityHelper.GetCurrentIntegrityLevel() && !allowHigherIntegrity)
243+
return false;
244+
245+
if ((int)InputArguments.GetIntegrityLevel() > SecurityHelper.GetCurrentIntegrityLevel())
243246
return false;
244247

245248
if (InputArguments.UserName != null && InputArguments.UserName != WindowsIdentity.GetCurrent().Name)

src/gsudo/Commands/ServiceCommand.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class ServiceCommand : ICommand, IDisposable
2828

2929
void EnableTimer()
3030
{
31+
if (CacheDuration > TimeSpan.FromDays(24)) CacheDuration = TimeSpan.FromDays(24);
32+
3133
if (CacheDuration != TimeSpan.MaxValue)
3234
ShutdownTimer.Change((int)CacheDuration.TotalMilliseconds, Timeout.Infinite);
3335
}
@@ -55,7 +57,7 @@ public async Task<int> Execute()
5557
|| (InputArguments.RunAsSystem && !System.Security.Principal.WindowsIdentity.GetCurrent().IsSystem)
5658
|| (InputArguments.UserName != null && !SecurityHelper.IsAdministrator() && SecurityHelper.IsMemberOfLocalAdmins())
5759
)*/
58-
if (!RunCommand.IsRunningAsDesiredUser())
60+
if (!RunCommand.IsRunningAsDesiredUser(allowHigherIntegrity: true))
5961
{
6062
Logger.Instance.Log("This service is not running with desired credentials. Starting a new service instance.", LogLevel.Info);
6163
#if DEBUG

src/gsudo/Commands/StatusCommand.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private static void PrintToConsole(Dictionary<string, object> result)
152152

153153
foreach (string s in result["CacheSessions"] as string[])
154154
{
155-
Console.WriteLine($" {s},");
155+
Console.WriteLine($" {s}");
156156
}
157157

158158
if ((bool)result["IsRedirected"])

0 commit comments

Comments
 (0)