majorwiki/05-troubleshooting/networking/windows-openssh-wsl-default-shell-breaks-remote-commands.md
majorlinux 91455fac39 Add 7 articles; update nav and existing articles (2026-04-25)
New articles:
- pihole-doh-dot-bypass-defense
- pihole-v6-adlist-management
- mastodon-db-maintenance
- mastodon-federation
- fantastical-google-phantom-calendar-syncselect
- rsync-tailscale-teardown-stall
- ollama-chat-template-pipe-stdin-bypass

Updated: wsl2-backup, wsl2-rebuild, ssh-config-key-management,
selfhosting index, mastodon-instance-tuning, ansible-check-mode,
windows-openssh, windows-sshd, yt-dlp, README, SUMMARY, index
Removed: fedora-usrmerge-ebtables-blocker (superseded by prior push)
2026-04-25 17:52:48 +00:00

3.8 KiB

title domain category tags status created updated
Windows OpenSSH: WSL as Default Shell Breaks Remote Commands troubleshooting networking
windows
openssh
wsl
ssh
majorrig
powershell
published 2026-04-03 2026-04-22T09:20

Windows OpenSSH: WSL as Default Shell Breaks Remote Commands

Problem

SSH remote commands fail with:

Invalid command line argument: -c
Please use 'wsl.exe --help' to get a list of supported arguments.

This happens on every remote command — ssh-copy-id, ssh user@host "command", scp, etc. Interactive SSH (no command) may still work if it drops into WSL.

Cause

Windows OpenSSH's default shell is set to C:\Windows\System32\wsl.exe. When SSH executes a remote command, it invokes:

<default_shell> -c "<command>"

But wsl.exe does not accept the -c flag. It expects -e for command execution, or no flags for an interactive session. Since OpenSSH hardcodes -c, every remote command fails.

bash.exe is a WSL shim that does accept the -c flag. This gives you a Linux-first SSH experience where both interactive sessions and remote commands work natively.

# Find the actual path to bash.exe (it varies by install)
Get-Command bash.exe | Select-Object Source

# Set it as the default shell (elevated PowerShell)
Set-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\bash.exe"
Restart-Service sshd

Note: bash.exe may not be at C:\Windows\System32\bash.exe on all installs. Always verify the path with Get-Command first — the Windows Store WSL install places it under AppData\Local\Microsoft\WindowsApps\.

After the fix (bash.exe)

  • Interactive SSH sessions land directly in your WSL distro
  • Remote SSH commands execute in WSL's bash — Linux commands work natively
  • ssh user@host "uname -s" returns Linux

Fix — Option 2: Revert to PowerShell

If you need Windows-native command execution over SSH (e.g., for Windows-targeted Ansible or remote PowerShell administration), set the default shell back to PowerShell:

Set-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
Restart-Service sshd

After the fix (PowerShell)

  • Remote SSH commands execute via PowerShell
  • To run Linux commands, prefix with wsl:
    ssh user@host "wsl bash -c 'cd /mnt/d/project && git pull'"
    
  • Interactive SSH sessions land in PowerShell (type wsl to enter Linux)
  • ssh-copy-id still won't work for WSL's authorized_keys — Windows OpenSSH reads from C:\Users\<user>\.ssh\authorized_keys, not the WSL home directory

Key Notes

  • This registry key (HKLM:\SOFTWARE\OpenSSH\DefaultShell) is the only supported way to change the OpenSSH default shell on Windows
  • The change persists across reboots and Windows Updates
  • wsl.exe does not support -c — never use it as the default shell
  • bash.exe does support -c — use it for a Linux-first SSH experience
  • The path to bash.exe varies by install method — always verify with Get-Command bash.exe
  • Tools like Ansible, scp, rsync, and ssh-copy-id all depend on -c working
  • If the shell path in the registry doesn't exist on disk, sshd will reject the user entirely with User <name> not allowed because shell <path> does not exist — check Get-WinEvent -LogName OpenSSH/Operational to diagnose