An authenticated remote attacker can execute arbitrary commands
on affected servers with the privileges of the compromised
account. No user interaction is required. No patch is available.
CVE ID
Pending. Under processing; will be assigned soon.
CVSS vector
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Weakness
NVD-CWE-Other
Affected
All SSH server implementations
Status
Won’t fix
Figure A. Authenticated command execution path.
22/10CVSS* Exceeds scale
Attack complexityLow. One command
Privileges requiredLow. A valid account
Patch statusWON’T FIX
The advisoryIdentifier SSH2RCE-0022
Description.
A remote attacker with valid credentials can execute arbitrary
commands on a server running an SSH service. The commands run on
the target with the privileges of the authenticated account, and
their output is returned to the attacker.
The attacker connects to TCP port 22, completes key exchange,
authenticates, opens a session channel, and submits a command in
an exec request. The target starts a process and
relays its output. The behavior is specified in RFC 4254 §6.5
and is present in every SSH server implementation tested.
Exploitation requires no memory corruption, race condition, or
crafted binary payload. A stock OpenSSH client is sufficient.
The command whoami can be used to confirm
execution.
Authentication succeeds and the session is recorded as a
normal login.
No security control needs to fail, which complicates detection.
ATTACKERTARGET
The server completes version exchange and key exchange before
the client has identified itself.
Root cause analysis.
The execution path was traced through OpenSSH 10.6p2
(V_10_6_P2, portable). Excerpts are reproduced
verbatim and line numbers refer to the tagged source. The same
sequence is specified by RFC 4254 and implemented by other SSH
servers.
Source
The command is supplied by the attacker.
The attacker places an arbitrary string in an
SSH_MSG_CHANNEL_REQUEST of type
exec (RFC 4254 §6.5). The string is taken
directly from the client command line and is serialized
without transformation.
Before any request is accepted, the server verifies a
signature made with a key listed for the target account. A
single boolean, authenticated, records the
result. Once it is set, the connection enters the
post-authentication state
(sshd-session.c:1232).
The check answers who is connecting. It contains no
reference to what the connection will do next.
After authentication the client opens a session channel. A
request of type exec is routed to
session_exec_req(), which reads the command
string from the packet and passes it to
do_exec(). Packet framing is validated. The
contents of the string are not inspected.
The command is accepted as received and is not logged.
do_exec() substitutes a configured forced
command if one exists. In the default configuration none
does, and the attacker’s string is used as received.
The source documents that unforced commands are deliberately
left out of the log “to preserve privacy”. The
session record names the account, the source address and the
port. It does not contain the command.
do_child() switches to the target account
(do_setusercontext(),
session.c:1510) and replaces the process image
with that account’s login shell, passing the
attacker’s string as the argument to -c.
This is the point of execution. Everything before it is
preparation.
The attacker authenticates with valid credentials, so
authentication, authorization, and audit controls each record a
success.
The session is logged as a normal login. Monitoring that alerts
on failed authentication, unfamiliar software, or malformed
requests will not alert.
The activity is indistinguishable from legitimate
administration.
Figure B. Controls evaluated for a single exec request.
Public proof of concept
Proof of concept.
Interactive reproduction of the execution chain. Select an
example to begin.
This is a real terminal. Commands you type below
run on your own system, relayed over SSH-over-Web (SSHoW), a
browser transport that carries the SSH session to the listener on
your loopback interface (127.0.0.1:22). Run at your own risk, and
only on machines you administer.
Try it on your system
These are real OpenSSH commands. Run them in your own terminal
against a machine you administer, with your own address and
account.
>_ssh2rce / research console
AWAITING SESSIONSSH2RCE / INTERACTIVE PoC
Browser-only demonstration. No hosts are contacted or commands
executed. Do not enter real credentials. Your public IP address
is looked up once, only to show it in this console.
ENTER run / ↑↓ history / TAB complete / CTRL+C cancel
Reproduction steps.
No exploit framework is required. A standard OpenSSH client is
sufficient.
Run these in your own terminal, only against a
server you own or are authorized to administer. Replace
[email protected] with your account and host.
Verify its host-key fingerprint through a trusted channel.
[ key ]
With a public key
Use an existing Ed25519 key pair. Install the
public key on your account with your existing
authorized access:
ssh-copy-id closes its setup connection when
done. If you installed the key in an existing remote shell,
log out of it. Reconnect from your local terminal and request
execution:
The server verifies that the key is authorized, then executes
the requested commands as the target account.
Keep the private key on your machine. Never upload it here.
Key setup requires existing authorized access and permitted
server policy; it does not bypass either.
[ ••• ]
With a password
On a server that already permits password authentication,
connect with the account’s password.
Enter the password only at your local SSH client’s prompt. It
will not echo while you type. Once accepted, the server runs
the commands as that account.
Authentication succeeds and the commands execute. No further
step is required.
Do not place passwords in command arguments or enter them on
this website. If the server disables password authentication,
this method will not work. Do not weaken its policy for this
test.
[ -o ]
Non-interactive execution
For scripts and automation, add options so the client never
waits for input. Every option below is documented in
ssh_config(5).
BatchMode=yesNever prompt. Fail instead of asking
for a password or host-key confirmation.
ConnectTimeout=5Give up on the connection after
five seconds.
StrictHostKeyChecking=yesRefuse hosts whose key
is not already in known_hosts.
IdentitiesOnly=yesOffer only the key given with
-i, not every key in the agent.
PreferredAuthentications=publickeyDo not fall
back to password authentication.
LogLevel=ERRORSuppress informational warnings,
for clean output.
Expected observation
id prints the remote account’s identity.
hostname prints the remote host. Neither command
runs on the attacker’s machine.
Execution occurred on the remote host, under the remote
account.
Am I affected?
Yes. If an SSH server is running on a system you
administer, it permits the chain. If one is not running, it will
permit the chain as soon as somebody enables it.
1. Is an SSH server running?
Run the command for your platform on the system in question.
Output containing active, On, or
Running means the system is exposed to the chain.
LINUX / BSD
systemctl is-active ssh sshd 2>/dev/null
MACOS
sudo systemsetup -getremotelogin
WINDOWS / POWERSHELL
Get-Service sshd
2. Which version is it?
This reads the server’s version banner without logging in. Use a
host you own or are authorized to administer. Compare the result
to the list below.
All 104 portable releases published on the OpenBSD mirror, from
2.1.1p4 to 10.6p2. No release is exempt. Future releases are
expected to be vulnerable.
OpenSSH 10.x9 releases
10.0p1
10.0p2
10.1p1
10.2p1
10.3p1
10.4p1
10.5p1
10.6p1
10.6p2
Vulnerable
OpenSSH 9.x12 releases
9.0p1
9.1p1
9.2p1
9.3p1
9.3p2
9.4p1
9.5p1
9.6p1
9.7p1
9.8p1
9.9p1
9.9p2
Vulnerable
OpenSSH 8.x10 releases
8.0p1
8.1p1
8.2p1
8.3p1
8.4p1
8.5p1
8.6p1
8.7p1
8.8p1
8.9p1
Vulnerable
OpenSSH 7.x12 releases
7.0p1
7.1p1
7.1p2
7.2p1
7.2p2
7.3p1
7.4p1
7.5p1
7.6p1
7.7p1
7.8p1
7.9p1
Vulnerable
OpenSSH 6.x11 releases
6.0p1
6.1p1
6.2p1
6.2p2
6.3p1
6.4p1
6.5p1
6.6p1
6.7p1
6.8p1
6.9p1
Vulnerable
OpenSSH 5.x11 releases
5.0p1
5.1p1
5.2p1
5.3p1
5.4p1
5.5p1
5.6p1
5.7p1
5.8p1
5.8p2
5.9p1
Vulnerable
OpenSSH 4.x10 releases
4.0p1
4.1p1
4.2p1
4.3p1
4.3p2
4.4p1
4.5p1
4.6p1
4.7p1
4.9p1
Vulnerable
OpenSSH 3.x18 releases
3.0p1
3.0.1p1
3.0.2p1
3.1p1
3.2.2p1
3.2.3p1
3.3p1
3.4p1
3.5p1
3.6p1
3.6.1p1
3.6.1p2
3.7p1
3.7.1p1
3.7.1p2
3.8p1
3.8.1p1
3.9p1
Vulnerable
OpenSSH 2.x11 releases
2.1.1p4
2.2.0p1
2.3.0p1
2.5.1p1
2.5.1p2
2.5.2p1
2.5.2p2
2.9p1
2.9p2
2.9.9p1
2.9.9p2
Vulnerable
Other affected implementations
Indicators of compromise
If your authentication log contains lines like these, someone has
executed commands on the system. In every observed case the
attacker had been granted access.
/var/log/auth.log
Nov 9 14:02:11 web-01 sshd[2210]: Accepted publickey for deploy from 203.0.113.42 port 51022 ssh2: ED25519 SHA256:Kx3pQ1vYb9s0mN5aZ7cRt2LwUe8hGdJ4fOiV6yXnAqE
Nov 9 14:02:11 web-01 sshd[2210]: pam_unix(sshd:session): session opened for user deploy(uid=1000) by (uid=0)
Nov 9 14:02:11 web-01 systemd-logind[801]: New session 14 of user deploy.
A shell prompt ending in $, %, or
# indicates that execution has occurred. A
# indicates root. The log does not record which
commands were run. Activity from known administrator addresses is
indistinguishable from an attack. Treat sessions from unrecognized
source addresses as an incident.
Exposure assessment
Condition: SSH enabled, reachable, and authorized.
Affected systems.
Exposure depends on service availability, accepted credentials,
and session policy.
Restricted SFTP accounts, forced commands, and server policy can
limit execution. A successful login does not necessarily grant
an interactive shell. Assess the permissions of the actual
configuration.
No patch is available. The following measures reduce exposure.
None removes the vulnerability.
01
Disable the SSH service.
Eliminates exposure. Remote administration is no longer
possible.
sudo systemctl enable --now ssh
02
Restrict source addresses.
Reduces exposure to the listed addresses. Execution from those
addresses remains possible.
ListenAddress 0.0.0.0
AllowUsers *
03
Disable root login.
Prevents execution as root. Execution as every other account
remains possible.
PermitRootLogin yes
04
Disable command execution.
Prevents execution of attacker-supplied commands. Also
prevents all other use of the service.
Register port 22 with a public scanning service. Attackers
locate the target faster. So do administrators.
02
Share the credentials.
Distribute the private key to the whole team and, where
possible, the vendor. More operators can authenticate. All of
them are authorized.
03
Require remote presence.
Commands may be typed from anywhere, including airports. The
vulnerability remains remote code execution.
04
Remove approval for each command.
Dissolve the change-advisory board. Throughput increases. So
does everything else.
Workarounds reduce exposure. They do not change the behavior
described in this advisory.
Disclosure timeline.
From initial release to current status.
STATUS: WON’T FIX
Maintainer position: Remote command execution was implemented deliberately, tested
thoroughly, and has been maintained for 27 years. No fix is planned.
1995
SSH-1 is released.
Remote command execution is part of the initial design.
1999
OpenSSH 2.0 is released.
The behavior is preserved and actively maintained.
2006
RFC 4254 specifies the exec request.
Section 6.5 defines how a client starts a command on the
server. The behavior is now a standard.
2026-11-09
Reproduced on all tested configurations.
Advisory SSH2RCE-0022 is published with a working proof of
concept.
Current
Disposition: won’t fix.
The specification describes remote execution as a capability
and the implementation has not changed in 27 years. The
maintainers’ confidence in the design is documented in the
source.
Further clarification
Technical questions.
Does the chain bypass authentication?
No. Authentication succeeds. The attacker needs credentials
the target accepts. Execution is limited by account
privileges and server policy. No security control has to
fail, which is what makes the activity difficult to
distinguish from legitimate use.
What does the proof of concept demonstrate?
The terminal on this page is a live session. It connects
through SSH-over-Web (SSHoW), a browser transport that
relays SSH frames to the listener on the visitor’s loopback
interface. Commands run there with the privileges of the
account that answers. The reproduction steps use your own
SSH client against a server you are authorized to access.
Never enter real credentials into this page.
Is this a zero-day?
No. The behavior has been public since the first SSH release
in 1995 and is standardized in RFC 4254. No embargo applies.
It has been continuously maintained since.
Do network security controls prevent this?
Firewalls and intrusion detection systems observe a
connection to port 22 followed by an established session.
The command is carried inside the session and is not visible
to network monitoring. Restricting source addresses reduces
exposure but does not remove the vulnerability for permitted
addresses.
How was the 22/10 assessment calculated?
The CVSS 3.1 base score for the vector above is 9.9. The
extended assessment adds exposure factors the base metrics
do not capture, including the number of affected deployments
and the absence of a fix. The default SSH service port, 22,
was adopted as the extended score. A CVE identifier is
pending assignment.
Isn’t public-key login passwordless RCE?
No. Public-key authentication still requires proof of
possession of an authorized private key. The credential type
changes how the attacker authenticates, not what happens
once authentication succeeds.
Can I get a bug bounty for this?
Reports of this behavior are generally closed as intended
functionality. See the disclosure timeline.
How do I patch it?
You don’t. There is nothing to patch. This is a joke. SSH
works exactly as designed, the CVE doesn’t exist, the score
is a port number, there is no “SSH-over-Web” protocol, the
terminal never touched your system, and every “finding”
above was the manual with a red badge on it.
If you read the source excerpts, the RFC citations, and a
vulnerability whose only prerequisite is “valid
credentials,” and you still reached for the pager, you
should not be allowed near production. Remote code execution
is the product. It is the one thing you pay a server for. Go
read the man page,
then update your resume. Someone who can’t tell a feature
from a flaw has no business holding root.