Bug 2458620 - CVE-2026-4631 cockpit: Cockpit: Unauthenticated remote code execution due to SSH command-line argument injection
Summary: CVE-2026-4631 cockpit: Cockpit: Unauthenticated remote code execution due to ...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: cockpit
Version: 44
Hardware: All
OS: Linux
unspecified
urgent
Target Milestone: ---
Assignee: Martin Pitt
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard: AcceptedBlocker
Depends On:
Blocks: F44FinalBlocker
TreeView+ depends on / blocked
 
Reported: 2026-04-15 07:20 UTC by tk2345_
Modified: 2026-04-17 05:29 UTC (History)
11 users (show)

Fixed In Version: cockpit-360.1-1.fc44
Clone Of: CVE-2026-4631
Environment:
Last Closed: 2026-04-16 23:41:33 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description tk2345_ 2026-04-15 07:20:08 UTC
+++ This bug was initially created as a clone of Bug #2450246 +++

By default, Cockpit supports logging into remote machines via SSH 
(https://github.com/cockpit-project/cockpit/blob/main/doc/authentication.md#remote-machines). 
While previous Cockpit versions used the dedicated cockpit-ssh helper 
(based on libssh), Cockpit since version 326/327 executes "python3 -m 
cockpit.beiboot", which in turn invokes the OpenSSH "ssh" client to 
connect to remote machines. The SSH "connect to" feature is available 
prior to authentication, meaning an attacker with access to the Cockpit 
webservice can trigger the execution of ssh on the Cockpit host. To be 
precise: the beiboot process is spawned as part of the authentication 
flow, but the attacker only needs to supply an arbitrary "Authorization: 
Basic" header with any credentials (even invalid ones) in a request to 
"/cockpit+=<hostname>/login" to trigger the ssh invocation. The injected 
commands execute before SSH authentication completes or fails.

The security issue is that SSH connection parameters are passed down as 
command-line arguments to ssh without any validation or sanitization. 
Neither cockpit-ws (C code in cockpitauth.c / cockpitauthorize.c) nor 
cockpit.beiboot (Python code in beiboot.py) performs any character or 
format checks on the username or hostname before passing them to the ssh 
process. In particular, this allows an attacker to invoke ssh on the 
Cockpit host with an arbitrary username and hostname during the login flow.

The resulting ssh invocation looks like (simplified; additional options 
like -o NumberOfPasswordPrompts=1 are omitted for clarity):

    arg0: ssh
    arg1: -l
    arg2: <username>
    arg3: <hostname>
    arg4: python3 -ic '# cockpit-bridge'

An attacker has full control over <username> and near-full control over 
<hostname> (some characters like whitespace and slashes cannot be used 
because the hostname is extracted from the URL path). Notably, there is 
no "--" separator between the ssh options and the destination argument, 
which enables option injection via the hostname field.

This leads to the following two vulnerabilities:

(1) Injection of malicious remote username leading to RCE

SSH allows the use of the remote username as a variable in SSH 
configuration files via the %r token. A potential SSH configuration 
could be:

    Match exec "/usr/bin/test %r = blocked_user"
        ProxyCommand /bin/false

With this configuration, ssh executes the command "/usr/bin/test 
<username> = blocked_user" during connection setup. Since %r is expanded 
before the command is passed to the shell, an attacker can inject 
arbitrary shell commands through the username. For example, using the 
username "x; touch /tmp/flag; #" would cause ssh to execute:

    /usr/bin/test x; touch /tmp/flag; # = blocked_user

The command injection occurs before ssh validates the username format. 
Although ssh ultimately terminates with "remote username containing 
invalid characters", the injected command ("touch /tmp/flag") has 
already been executed.

This means if the Cockpit host's ssh_config uses %r in a "Match exec" 
directive, Cockpit is vulnerable to unauthenticated remote code execution.

I am in parallel in contact with the OpenSSH maintainers to get this 
problem fixed in OpenSSH as well, though I believe it is also an issue 
in Cockpit for passing unverified data to ssh.

(2) Injection of malicious hostname leading to RCE

Since the hostname is passed as a positional argument to ssh without a 
preceding "--" separator (see via_ssh() in beiboot.py), an attacker can 
inject SSH options by supplying a hostname that starts with "-". For 
example, the attacker can pass "-oProxyCommand=<malicious_command>" as 
the hostname via the URL path 
"/cockpit+=-oProxyCommand=<malicious_command>/login".

ProxyCommand is an SSH client option that executes a specified program 
whenever SSH connects to a remote host. When the original hostname field 
is consumed as an option instead of a hostname, ssh interprets the next 
positional argument, which is "python3 -ic '# cockpit-bridge'" (the 
remote command), as the actual hostname. This means the malicious 
ProxyCommand is executed as ssh attempts to "connect" to this 
misinterpreted hostname.

Fortunately, OpenSSH version 9.6 introduced early hostname validation 
that bans shell metacharacters in command-line hostnames and usernames 
(https://github.com/openssh/openssh-portable/commit/7ef3787) before 
establishing an SSH connection. With OpenSSH >= 9.6, the command 
injection via "-oProxyCommand=<malicious_command>" fails because 
"python3 -ic '# cockpit-bridge'" contains invalid hostname characters 
(spaces, quotes, etc.), and ssh aborts before executing the 
ProxyCommand. Nevertheless, on older OpenSSH versions, this check is not 
available and <malicious_command> will be executed by OpenSSH in an 
attempt to connect to "python3 -ic '# cockpit-bridge'".

The probability that a Cockpit host is vulnerable to this depends on the 
OpenSSH version installed. Cockpit migrated to the beiboot/OpenSSH path 
in version 327 (released 2024-10-23), while OpenSSH 9.6 was released on 
2023-12-18, which is roughly 10 months earlier. Systems that upgraded 
Cockpit to >= 327 but did not update OpenSSH to >= 9.6 would be 
vulnerable to unauthenticated remote code execution via hostname injection.

Potential fix:

1. Add a "--" separator before the destination argument in via_ssh() 
(beiboot.py) to prevent option injection via the hostname. This directly 
mitigates vulnerability (2).
2. Validate both username and hostname using a character allowlist 
before passing them to ssh. Examples for such validation can be found in 
OpenSSH's source code: valid_hostname() and valid_ruser() in ssh.c. This 
mitigates both vulnerabilities (1) and (2).

Summary:

While the preconditions for these vulnerabilities will likely affect 
only a subset of Cockpit installations, the impact is critical: 
unauthenticated remote code execution on the Cockpit host. An attacker 
with network access to the Cockpit webservice can trigger the exploit 
with a single crafted HTTP request to the login endpoint. No valid 
credentials are required, as the injection occurs during the 
authentication flow before SSH authentication completes.

--- Additional comment from Jelle van der Waa on 2026-04-10 13:48:16 UTC ---

Not sure how this is usually handled, but Cockpit 360 with the fix has been proposed to F43/F44 and rawhide, I have backported the fix to Fedora 42 and the pull request for it is currently open. https://src.fedoraproject.org/rpms/cockpit/pull-request/422

Comment 1 Fedora Blocker Bugs Application 2026-04-15 07:21:23 UTC
Proposed as a Blocker for 44-final by Fedora user tk2345 using the blocker tracking app because:

 Critical severity, https://access.redhat.com/security/cve/cve-2026-4631

The issue seems to get fixed together with https://bugzilla.redhat.com/show_bug.cgi?id=2455855. If the fix for 2455855 does not make into F44, this issue remains open.

Comment 2 Fedora Update System 2026-04-15 09:21:50 UTC
FEDORA-2026-ea792bf240 (cockpit-360.1-1.fc44) has been submitted as an update to Fedora 44.
https://bodhi.fedoraproject.org/updates/FEDORA-2026-ea792bf240

Comment 3 Adam Williamson 2026-04-15 14:50:12 UTC
+4 in https://pagure.io/fedora-qa/blocker-review/issue/2110 , marking accepted blocker.

Just to double triple check: this is fixed in cockpit-360.1-1.fc44 , yes? Because that build is already in RC-1.2, so we should be good already. Please check, though.

Comment 4 Jelle van der Waa 2026-04-16 13:09:37 UTC
Adam, yes the CVE was fixed in 360 so it was also fixed in 360.1 The commit which fixes it is https://github.com/cockpit-project/cockpit/commit/9d0695647cb6f6209e68231fd165917123aa502d

Comment 5 Fedora Update System 2026-04-16 23:41:33 UTC
FEDORA-2026-ea792bf240 (cockpit-360.1-1.fc44) has been pushed to the Fedora 44 stable repository.
If problem still persists, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.