Adding parameters to DefaultShell in Windows OpenSSH Server (e.g. powershell.exe -NoLogo)

I have Windows OpenSSH server installed and working properly. I can change the default shell that is ssh'd into using HKLM:\SOFTWARE\OpenSSH and adding a DefaultShell property as described here.

So let's go with the default example, since it works as-is on pretty much every Windows installation with the "normal" C:\Windows path:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force

Now let's say that I want to add a parameter to it, perhaps "-NoLogo". This is just a for-instance. Ultimately, I'd want to be able to launch into a WSL distribution with options. But for now, let's go simple:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo" -PropertyType String -Force

This not only doesn't work, it breaks the login in strange ways. With the first method (no arguments), my public key in ssh-agent is offered and accepted. When I add the -NoLogo, I end up at a password prompt, which fails using my Windows password.

Running sshd.exe -ddd shows:

User not allowed because shell c:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe -nologo does not exist

Okay, so that's not going to work, because OpenSSH checks to make sure the exact DefaultShell string is an executable.

I see that there are two other registry settings, but neither seems to be what I'm looking for. One might think from its name that DefaultShellCommandOption would be of some use here, but it is simply the option needed for the shell when a command is passed in, such as:

ssh hostname ls

Since one of the attempted answers here thought DefaultShellCommandOption would do the trick, I did try it, and confirmed that it is only used when a command is passed in. I can also see in the OpenSSH source that shell_option is only used when there is a command, otherwise it only executes the shell by itself:

if (command) {
    size_t len = strlen(shell) + 1 + strlen(shell_option) + 1 + strlen(command) + 1;
    pty_cmd = calloc(1, len);

    strcpy_s(pty_cmd, len, shell);
    strcat_s(pty_cmd, len, " ");
    strcat_s(pty_cmd, len, shell_option);
    strcat_s(pty_cmd, len, " ");
    strcat_s(pty_cmd, len, command);
} else {
    pty_cmd = shell;
}

Is anyone aware of a way to add parameters/arguments to the DefaultShell in Windows OpenSSH?


Potential Workaround

Once I noticed that OpenSSH was checking to make sure the DefaultShell existed and was executable, I decided to just try creating a batch file wrapping the PowerShell options.

I created a directory and file C:\ProgramData\OpenSSH\ssh-shell.bat:

@echo off
C:\Windows\System32\WindowsPowerShell/v1.0/powershell.exe -NoLogo %*

And changed my DefaultShell to run that wrapper (from an elevated PowerShell):

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\ProgramData\OpenSSH\ssh-shell.bat" -PropertyType String -Force

That seems to work as desired, both for access to the shell itself as well as when running with a command (e.g. ssh hostname ls).

It is also possible to launch directly into a specified WSL distribution this way:

@echo off
C:\Windows\System32\wsl.exe ~ -d Alpine %*

Note that this does require that the DefaultShellCommandOption also be changed:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShellCommandOption -Value "-e /bin/sh -c" -PropertyType String -Force

Security Implications

This feels like it is just as safe as the default OpenSSH DefaultShell behavior, since it builds the commandline using the actual shell (plus my desired additional arguments), the DefaultShellCommandOption (-c by default), and the command(s) that are passed in.

But I'm open to suggestions on how this might be made more robust or secure, or if there are any security issues that one might see.