--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:openssh
User: [email protected]
Usertags: pu
[ Reason ]
OpenSSH 10.3 included several minor security updates. The security team
has marked them no-dsa, but I'd like to fix them in an oldstable update.
[ Impact ]
Several security issues that are minor for most people although major in
some situations (in particular, CVE-2026-35414 can be an authentication
bypass in some configurations).
[ Tests ]
The OpenSSH packaging runs an extensive set of automated tests via
autopkgtest, some of which are adjusted for some of the security
updates.
[ Risks ]
There are two intentional incompatibilities introduced by the security
updates (descriptions here are from the upstream release notes):
* sshd(8): prior to this release, a certificate that had an empty
principals section would be treated as matching any principal (i.e. as a
wildcard) when used via authorized_keys principals="" option. This was
intentional, but created a surprising and potentially risky situation if
a CA accidentally issued a certificate with an empty principals section:
instead of being useless as one might expect, it could be used to
authenticate as any user who trusted the CA via authorized_keys. [Note
that this condition did not apply to CAs trusted via the sshd_config(5)
TrustedUserCAKeys option.]
This release treats an empty principals section as never matching any
principal, and also fixes interpretation of wildcard characters in
certificate principals. Now they are consistently implemented for host
certificates and not supported for user certificates.
* ssh(1): the -J and equivalent -oProxyJump="..." options now validate
user and host names for ProxyJump/-J options passed via the command-line
(no such validation is performed for this option in configuration
files). This prevents shell injection in situations where these were
directly exposed to adversarial input, which would have been a terrible
idea to begin with.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
Thanks,
--
Colin Watson (he/him) [[email protected]]
diff -Nru openssh-9.2p1/debian/.git-dpm openssh-9.2p1/debian/.git-dpm
--- openssh-9.2p1/debian/.git-dpm 2026-04-05 00:33:20.000000000 +0100
+++ openssh-9.2p1/debian/.git-dpm 2026-05-03 19:16:45.000000000 +0100
@@ -1,6 +1,6 @@
# see git-dpm(1) from git-dpm package
-f17eedbd2398f00fbb96170b60c8d2895318223e
-f17eedbd2398f00fbb96170b60c8d2895318223e
+7a182a79ead6b39b0450059e07ffb2ce02ebd323
+7a182a79ead6b39b0450059e07ffb2ce02ebd323
cf3c3acb2b8f74eeca7fcee269b1d33ac83f1188
cf3c3acb2b8f74eeca7fcee269b1d33ac83f1188
openssh_9.2p1.orig.tar.gz
diff -Nru openssh-9.2p1/debian/changelog openssh-9.2p1/debian/changelog
--- openssh-9.2p1/debian/changelog 2026-04-05 00:33:31.000000000 +0100
+++ openssh-9.2p1/debian/changelog 2026-05-03 19:16:45.000000000 +0100
@@ -1,3 +1,56 @@
+openssh (1:9.2p1-2+deb12u10) UNRELEASED; urgency=medium
+
+ * Backport minor security fixes from 10.3p1:
+ - ssh(1): the -J and equivalent -oProxyJump="..." options now validate
+ user and host names for ProxyJump/-J options passed via the
+ command-line (no such validation is performed for this option in
+ configuration files). This prevents shell injection in situations
+ where these were directly exposed to adversarial input, which would
+ have been a terrible idea to begin with.
+ - CVE-2026-35386: ssh(1): validation of shell metacharacters in user
+ names supplied on the command-line was performed too late to prevent
+ some situations where they could be expanded from %-tokens in
+ ssh_config. For certain configurations, such as those that use a "%u"
+ token in a "Match exec" block, an attacker who can control the user
+ name passed to ssh(1) could potentially execute arbitrary shell
+ commands. Reported by Florian Kohnhäuser (closes: #1132573).
+ We continue to recommend against directly exposing ssh(1) and other
+ tools' command-lines to untrusted input. Mitigations such as this can
+ not be absolute given the variety of shells and user configurations in
+ use.
+ - CVE-2026-35414: sshd(8): when matching an authorized_keys
+ principals="" option against a list of principals in a certificate, an
+ incorrect algorithm was used that could allow inappropriate matching
+ in cases where a principal name in the certificate contains a comma
+ character. Exploitation of the condition requires an authorized_keys
+ principals="" option that lists more than one principal *and* a CA
+ that will issue a certificate that encodes more than one of these
+ principal names separated by a comma (typical CAs strongly constrain
+ which principal names they will place in a certificate). This
+ condition only applies to user- trusted CA keys in authorized_keys,
+ the main certificate authentication path
+ (TrustedUserCAKeys/AuthorizedPrincipalsFile) is not affected. Reported
+ by Vladimir Tokarev (closes: #1132576).
+ - CVE-2026-35385: scp(1): when downloading files as root in legacy (-O)
+ mode and without the -p (preserve modes) flag set, scp did not clear
+ setuid/setgid bits from downloaded files as one might typically
+ expect. This bug dates back to the original Berkeley rcp program.
+ Reported by Christos Papakonstantinou of Cantina and Spearbit (closes:
+ #1132572).
+ - CVE-2026-35387: sshd(8): fix incomplete application of
+ PubkeyAcceptedAlgorithms and HostbasedAcceptedAlgorithms with regard
+ to ECDSA keys. Previously if one of these directives contains any
+ ECDSA algorithm name (say "ecdsa-sha2-nistp384"), then any other ECDSA
+ algorithm would be accepted in its place regardless of whether it was
+ listed or not. Reported by Christos Papakonstantinou of Cantina and
+ Spearbit (closes: #1132574).
+ - CVE-2026-35388: ssh(1): connection multiplexing confirmation
+ (requested using "ControlMaster ask/autoask") was not being tested for
+ proxy mode multiplexing sessions (i.e. "ssh -O proxy ..."). Reported
+ by Michalis Vasileiadis (closes: #1132575).
+
+ -- Colin Watson <[email protected]> Sun, 03 May 2026 19:16:45 +0100
+
openssh (1:9.2p1-2+deb12u9) bookworm-security; urgency=medium
* CVE-2026-3497: Fix incorrect GSS-API error handling; Replace incorrect
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35385.patch
openssh-9.2p1/debian/patches/CVE-2026-35385.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35385.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35385.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,39 @@
+From d0d5ee1547b4fc7a3b355d15262f272682465a2f Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:42:16 +0000
+Subject: upstream: when downloading files as root in legacy (-O) mode and
+
+without the -p (preserve modes) flag set, clear setuid/setgid bits from
+downloaded files as one might expect.
+
+AFAIK this bug dates back to the original Berkeley rcp program.
+
+Reported by Christos Papakonstantinou of Cantina and Spearbit.
+
+OpenBSD-Commit-ID: 49e902fca8dd933a92a9b547ab31f63e86729fa1
+
+Origin: upstream,
https://anongit.mindrot.org/openssh.git/commit/?id=487e8ac146f7d6616f65c125d5edb210519b833a
+Bug-Debian: https://bugs.debian.org/1132572
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35385.patch
+---
+ scp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/scp.c b/scp.c
+index df590c4e3..77c854002 100644
+--- a/scp.c
++++ b/scp.c
+@@ -1677,8 +1677,10 @@ sink(int argc, char **argv, const char *src)
+
+ setimes = targisdir = 0;
+ mask = umask(0);
+- if (!pflag)
++ if (!pflag) {
++ mask |= 07000;
+ (void) umask(mask);
++ }
+ if (argc != 1) {
+ run_err("ambiguous target");
+ exit(1);
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35386-1.patch
openssh-9.2p1/debian/patches/CVE-2026-35386-1.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35386-1.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35386-1.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,318 @@
+From 03dbf03cf10c5ea273d909caefa3a105824a9ea0 Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Mon, 30 Mar 2026 07:18:24 +0000
+Subject: upstream: apply the same validity rules to usernames and hostnames
+
+set for ProxyJump/-J on the commandline as we do for destination user/host
+names.
+
+Specifically, they are no longer allowed to contain most characters
+that have special meaning for common shells. Special characters are
+still allowed in ProxyJump commands that are specified in the config
+files.
+
+This _reduces_ the chance that shell characters from a hostile -J
+option from ending up in a shell execution context.
+
+Don't pass untrusted stuff to the ssh commandline, it's not intended
+to be a security boundary. We try to make it safe where we can, but
+we can't make guarantees, because we can't know the parsing rules
+and special characters for all the shells in the world, nor can we
+know what the user does with this data in their ssh_config wrt
+percent expansion, LocalCommand, match exec, etc.
+
+While I'm in there, make ProxyJump and ProxyCommand first-match-wins
+between each other.
+
+reported by rabbit; ok dtucker@
+
+OpenBSD-Commit-ID: f05ad8a1eb5f6735f9a935a71a90580226759263
+
+Origin: backport,
https://anongit.mindrot.org/openssh.git/commit/?id=0a0ef4515361143cad21afa072319823854c1cf6
+Bug-Debian: https://bugs.debian.org/1132573
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35386-1.patch
+---
+ readconf.c | 124 +++++++++++++++++++++++++++++++++++++----------------
+ readconf.h | 4 +-
+ ssh.c | 48 +++------------------
+ 3 files changed, 95 insertions(+), 81 deletions(-)
+
+diff --git a/readconf.c b/readconf.c
+index 2db9cb6ae..a6e8303ff 100644
+--- a/readconf.c
++++ b/readconf.c
+@@ -1382,9 +1382,6 @@ parse_char_array:
+
+ case oProxyCommand:
+ charptr = &options->proxy_command;
+- /* Ignore ProxyCommand if ProxyJump already specified */
+- if (options->jump_host != NULL)
+- charptr = &options->jump_host; /* Skip below */
+ parse_command:
+ if (str == NULL) {
+ error("%.200s line %d: Missing argument.",
+@@ -1405,7 +1402,7 @@ parse_command:
+ }
+ len = strspn(str, WHITESPACE "=");
+ /* XXX use argv? */
+- if (parse_jump(str + len, options, *activep) == -1) {
++ if (parse_jump(str + len, options, cmdline, *activep) == -1) {
+ error("%.200s line %d: Invalid ProxyJump \"%s\"",
+ filename, linenum, str + len);
+ goto out;
+@@ -3101,65 +3098,116 @@ parse_forward(struct Forward *fwd, const char
*fwdspec, int dynamicfwd, int remo
+ }
+
+ int
+-parse_jump(const char *s, Options *o, int active)
++ssh_valid_hostname(const char *s)
+ {
+- char *orig, *sdup, *cp;
+- char *host = NULL, *user = NULL;
+- int r, ret = -1, port = -1, first;
++ size_t i;
+
+- active &= o->proxy_command == NULL && o->jump_host == NULL;
++ if (*s == '-')
++ return 0;
++ for (i = 0; s[i] != 0; i++) {
++ if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL ||
++ isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
++ return 0;
++ }
++ return 1;
++}
+
+- orig = sdup = xstrdup(s);
++int
++ssh_valid_ruser(const char *s)
++{
++ size_t i;
+
+- /* Remove comment and trailing whitespace */
++ if (*s == '-')
++ return 0;
++ for (i = 0; s[i] != 0; i++) {
++ if (iscntrl((u_char)s[i]))
++ return 0;
++ if (strchr("'`\";&<>|(){}", s[i]) != NULL)
++ return 0;
++ /* Disallow '-' after whitespace */
++ if (isspace((u_char)s[i]) && s[i + 1] == '-')
++ return 0;
++ /* Disallow \ in last position */
++ if (s[i] == '\\' && s[i + 1] == '\0')
++ return 0;
++ }
++ return 1;
++}
++
++int
++parse_jump(const char *s, Options *o, int strict, int active)
++{
++ char *orig = NULL, *sdup = NULL, *cp;
++ char *tmp_user = NULL, *tmp_host = NULL, *host = NULL, *user = NULL;
++ int r, ret = -1, tmp_port = -1, port = -1, first = 1;
++
++ if (strcasecmp(s, "none") == 0) {
++ if (active && o->jump_host == NULL) {
++ o->jump_host = xstrdup("none");
++ o->jump_port = 0;
++ }
++ return 0;
++ }
++
++ orig = xstrdup(s);
+ if ((cp = strchr(orig, '#')) != NULL)
+ *cp = '\0';
+ rtrim(orig);
+
+- first = active;
++ active &= o->proxy_command == NULL && o->jump_host == NULL;
++ sdup = xstrdup(orig);
+ do {
+- if (strcasecmp(s, "none") == 0)
+- break;
++ /* Work backwards through string */
+ if ((cp = strrchr(sdup, ',')) == NULL)
+ cp = sdup; /* last */
+ else
+ *cp++ = '\0';
+
++ r = parse_ssh_uri(cp, &tmp_user, &tmp_host, &tmp_port);
++ if (r == -1 || (r == 1 && parse_user_host_port(cp,
++ &tmp_user, &tmp_host, &tmp_port) != 0))
++ goto out; /* error already logged */
++ if (strict) {
++ if (!ssh_valid_hostname(tmp_host)) {
++ error_f("invalid hostname \"%s\"", tmp_host);
++ goto out;
++ }
++ if (tmp_user != NULL && !ssh_valid_ruser(tmp_user)) {
++ error_f("invalid username \"%s\"", tmp_user);
++ goto out;
++ }
++ }
+ if (first) {
+- /* First argument and configuration is active */
+- r = parse_ssh_uri(cp, &user, &host, &port);
+- if (r == -1 || (r == 1 &&
+- parse_user_host_port(cp, &user, &host, &port) != 0))
+- goto out;
+- } else {
+- /* Subsequent argument or inactive configuration */
+- r = parse_ssh_uri(cp, NULL, NULL, NULL);
+- if (r == -1 || (r == 1 &&
+- parse_user_host_port(cp, NULL, NULL, NULL) != 0))
+- goto out;
++ user = tmp_user;
++ host = tmp_host;
++ port = tmp_port;
++ tmp_user = tmp_host = NULL; /* transferred */
+ }
+ first = 0; /* only check syntax for subsequent hosts */
++ free(tmp_user);
++ free(tmp_host);
++ tmp_user = tmp_host = NULL;
++ tmp_port = -1;
+ } while (cp != sdup);
++
+ /* success */
+ if (active) {
+- if (strcasecmp(s, "none") == 0) {
+- o->jump_host = xstrdup("none");
+- o->jump_port = 0;
+- } else {
+- o->jump_user = user;
+- o->jump_host = host;
+- o->jump_port = port;
+- o->proxy_command = xstrdup("none");
+- user = host = NULL;
+- if ((cp = strrchr(s, ',')) != NULL && cp != s) {
+- o->jump_extra = xstrdup(s);
+- o->jump_extra[cp - s] = '\0';
+- }
++ o->jump_user = user;
++ o->jump_host = host;
++ o->jump_port = port;
++ o->proxy_command = xstrdup("none");
++ user = host = NULL; /* transferred */
++ if (orig != NULL && (cp = strrchr(orig, ',')) != NULL) {
++ o->jump_extra = xstrdup(orig);
++ o->jump_extra[cp - orig] = '\0';
+ }
+ }
+ ret = 0;
+ out:
+ free(orig);
++ free(sdup);
++ free(tmp_user);
++ free(tmp_host);
+ free(user);
+ free(host);
+ return ret;
+diff --git a/readconf.h b/readconf.h
+index d0eb92362..591b641cb 100644
+--- a/readconf.h
++++ b/readconf.h
+@@ -239,7 +239,9 @@ int process_config_line(Options *, struct passwd
*, const char *,
+ int read_config_file(const char *, struct passwd *, const char *,
+ const char *, Options *, int, int *);
+ int parse_forward(struct Forward *, const char *, int, int);
+-int parse_jump(const char *, Options *, int);
++int ssh_valid_hostname(const char *);
++int ssh_valid_ruser(const char *);
++int parse_jump(const char *, Options *, int, int);
+ int parse_ssh_uri(const char *, char **, char **, int *);
+ int default_ssh_port(void);
+ int option_clear_or_none(const char *);
+diff --git a/ssh.c b/ssh.c
+index a0371839b..e5ec18a73 100644
+--- a/ssh.c
++++ b/ssh.c
+@@ -623,43 +623,6 @@ ssh_conn_info_free(struct ssh_conn_info *cinfo)
+ free(cinfo);
+ }
+
+-static int
+-valid_hostname(const char *s)
+-{
+- size_t i;
+-
+- if (*s == '-')
+- return 0;
+- for (i = 0; s[i] != 0; i++) {
+- if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL ||
+- isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
+- return 0;
+- }
+- return 1;
+-}
+-
+-static int
+-valid_ruser(const char *s)
+-{
+- size_t i;
+-
+- if (*s == '-')
+- return 0;
+- for (i = 0; s[i] != 0; i++) {
+- if (iscntrl((u_char)s[i]))
+- return 0;
+- if (strchr("'`\";&<>|(){}", s[i]) != NULL)
+- return 0;
+- /* Disallow '-' after whitespace */
+- if (isspace((u_char)s[i]) && s[i + 1] == '-')
+- return 0;
+- /* Disallow \ in last position */
+- if (s[i] == '\\' && s[i + 1] == '\0')
+- return 0;
+- }
+- return 1;
+-}
+-
+ /*
+ * Main program for the ssh client.
+ */
+@@ -902,9 +865,9 @@ main(int ac, char **av)
+ }
+ if (options.proxy_command != NULL)
+ fatal("Cannot specify -J with ProxyCommand");
+- if (parse_jump(optarg, &options, 1) == -1)
++ if (parse_jump(optarg, &options, 1, 1) == -1)
++
+ fatal("Invalid -J argument");
+- options.proxy_command = xstrdup("none");
+ break;
+ case 't':
+ if (options.request_tty == REQUEST_TTY_YES)
+@@ -1152,7 +1115,7 @@ main(int ac, char **av)
+ if (!host)
+ usage();
+
+- if (!valid_hostname(host))
++ if (!ssh_valid_hostname(host))
+ fatal("hostname contains invalid characters");
+ options.host_arg = xstrdup(host);
+
+@@ -1314,7 +1277,8 @@ main(int ac, char **av)
+ sshbin = "ssh";
+
+ /* Consistency check */
+- if (options.proxy_command != NULL)
++ if (options.proxy_command != NULL &&
++ strcasecmp(options.proxy_command, "none") != 0)
+ fatal("inconsistent options: ProxyCommand+ProxyJump");
+ /* Never use FD passing for ProxyJump */
+ options.proxy_use_fdpass = 0;
+@@ -1438,7 +1402,7 @@ main(int ac, char **av)
+ * Conversely, usernames from getpwnam(3) or specified as literals
+ * via configuration are not subject to validation.
+ */
+- if (user_on_commandline && !valid_ruser(options.user))
++ if (user_on_commandline && !ssh_valid_ruser(options.user))
+ fatal("remote username contains invalid characters");
+
+ /*
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35386-2.patch
openssh-9.2p1/debian/patches/CVE-2026-35386-2.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35386-2.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35386-2.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,54 @@
+From d0b61d082621d45bf19f0aa04e9bbbc7e47e8f88 Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:50:55 +0000
+Subject: upstream: move username validity check for usernames specified on
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+the commandline to earlier in main(), specifically before some contexts where
+a username with shell characters might be expanded by a %u directive in
+ssh_config.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We continue to recommend against using untrusted input on
+the SSH commandline. Mitigations like this are not 100%
+guarantees of safety because we can't control every
+combination of user shell and configuration where they are
+used.
+
+Reported by Florian Kohnhäuser
+
+OpenBSD-Commit-ID: 25ef72223f5ccf1c38d307ae77c23c03f59acc55
+
+Origin: upstream,
https://anongit.mindrot.org/openssh.git/commit/?id=76685c9b09a66435cd2ad8373246adf1c53976d3
+Bug-Debian: https://bugs.debian.org/1132573
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35386-2.patch
+---
+ ssh.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/ssh.c b/ssh.c
+index e5ec18a73..ac06bbe74 100644
+--- a/ssh.c
++++ b/ssh.c
+@@ -1115,8 +1115,15 @@ main(int ac, char **av)
+ if (!host)
+ usage();
+
++ /*
++ * Validate commandline-specified values that end up in %tokens
++ * before they are used in config parsing.
++ */
++ if (options.user != NULL && !ssh_valid_ruser(options.user))
++ fatal("remote username contains invalid characters");
+ if (!ssh_valid_hostname(host))
+ fatal("hostname contains invalid characters");
++
+ options.host_arg = xstrdup(host);
+
+ /* Initialize the command to execute on remote host. */
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35386-3.patch
openssh-9.2p1/debian/patches/CVE-2026-35386-3.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35386-3.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35386-3.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,26 @@
+From 7a182a79ead6b39b0450059e07ffb2ce02ebd323 Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:52:15 +0000
+Subject: upstream: adapt to username validity check change
+
+OpenBSD-Regress-ID: d22c66ca60f0d934a75e6ca752c4c11b9f4a5324
+
+Origin: backport,
https://anongit.mindrot.org/openssh.git/commit/?id=5aa09926fbf050d484a79717fadec8360c5c5645
+Bug-Debian: https://bugs.debian.org/1132573
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35386-3.patch
+---
+ regress/percent.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/regress/percent.sh b/regress/percent.sh
+index 6b9c492b0..93fa4e17d 100644
+--- a/regress/percent.sh
++++ b/regress/percent.sh
+@@ -158,4 +158,4 @@ ${SSH} -F $OBJ/ssh_proxy -G "${FOO}@somehost" && fail
"user-at expanded env"
+
+ # Literal control characters in config is acceptable
+ verbose $tid user control-literal
+-trial user "$FOO" "$FOO"
++#trial user "$FOO" "$FOO"
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35387.patch
openssh-9.2p1/debian/patches/CVE-2026-35387.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35387.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35387.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,136 @@
+From 42a8064f37b82f65d3124eddafd078850132354a Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:48:13 +0000
+Subject: upstream: correctly match ECDSA signature algorithms against
+
+algorithm allowlists: HostKeyAlgorithms, PubkeyAcceptedAlgorithms and
+HostbasedAcceptedAlgorithms.
+
+Previously, if any ECDSA type (say "ecdsa-sha2-nistp521") was
+present in one of these lists, then all ECDSA algorithms would
+be permitted.
+
+Reported by Christos Papakonstantinou of Cantina and Spearbit.
+
+OpenBSD-Commit-ID: c790e2687c35989ae34a00e709be935c55b16a86
+
+[cjwatson: Committed upstream together with apparently-unrelated changes
+for CVE-2026-35414. I've split them into separate patches for clarity.]
+
+Origin: backport,
https://anongit.mindrot.org/openssh.git/commit/?id=fd1c7e131f331942d20f42f31e79912d570081fa
+Bug-Debian: https://bugs.debian.org/1132574
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35387.patch
+---
+ auth2-hostbased.c | 7 ++++---
+ auth2-pubkey.c | 7 ++++---
+ sshconnect2.c | 26 +++++++++++++++++---------
+ 3 files changed, 25 insertions(+), 15 deletions(-)
+
+diff --git a/auth2-hostbased.c b/auth2-hostbased.c
+index 6b517db41..74643cda1 100644
+--- a/auth2-hostbased.c
++++ b/auth2-hostbased.c
+@@ -96,9 +96,10 @@ userauth_hostbased(struct ssh *ssh, const char *method)
+ error_f("cannot decode key: %s", pkalg);
+ goto done;
+ }
+- if (key->type != pktype) {
+- error_f("type mismatch for decoded key "
+- "(received %d, expected %d)", key->type, pktype);
++ if (key->type != pktype || (sshkey_type_plain(pktype) == KEY_ECDSA &&
++ sshkey_ecdsa_nid_from_name(pkalg) != key->ecdsa_nid)) {
++ error_f("key type mismatch for decoded key "
++ "(received %s, expected %s)", sshkey_ssh_name(key), pkalg);
+ goto done;
+ }
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+diff --git a/auth2-pubkey.c b/auth2-pubkey.c
+index 5d59febc3..02e88115f 100644
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -148,9 +148,10 @@ userauth_pubkey(struct ssh *ssh, const char *method)
+ error_f("cannot decode key: %s", pkalg);
+ goto done;
+ }
+- if (key->type != pktype) {
+- error_f("type mismatch for decoded key "
+- "(received %d, expected %d)", key->type, pktype);
++ if (key->type != pktype || (sshkey_type_plain(pktype) == KEY_ECDSA &&
++ sshkey_ecdsa_nid_from_name(pkalg) != key->ecdsa_nid)) {
++ error_f("key type mismatch for decoded key "
++ "(received %s, expected %s)", sshkey_ssh_name(key), pkalg);
+ goto done;
+ }
+ if (sshkey_type_plain(key->type) == KEY_RSA &&
+diff --git a/sshconnect2.c b/sshconnect2.c
+index 0785717f2..6dbff4bbc 100644
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -90,6 +90,7 @@ extern Options options;
+ static char *xxx_host;
+ static struct sockaddr *xxx_hostaddr;
+ static const struct ssh_conn_info *xxx_conn_info;
++static int key_type_allowed(struct sshkey *, const char *);
+
+ static int
+ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
+@@ -99,6 +100,10 @@ verify_host_key_callback(struct sshkey *hostkey, struct
ssh *ssh)
+ if ((r = sshkey_check_rsa_length(hostkey,
+ options.required_rsa_size)) != 0)
+ fatal_r(r, "Bad server host key");
++ if (!key_type_allowed(hostkey, options.hostkeyalgorithms)) {
++ fatal("Server host key %s not in HostKeyAlgorithms",
++ sshkey_ssh_name(hostkey));
++ }
+ if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
+ xxx_conn_info) != 0)
+ fatal("Host key verification failed.");
+@@ -1777,34 +1782,37 @@ load_identity_file(Identity *id)
+ }
+
+ static int
+-key_type_allowed_by_config(struct sshkey *key)
++key_type_allowed(struct sshkey *key, const char *allowlist)
+ {
+- if (match_pattern_list(sshkey_ssh_name(key),
+- options.pubkey_accepted_algos, 0) == 1)
++ if (match_pattern_list(sshkey_ssh_name(key), allowlist, 0) == 1)
+ return 1;
+
+ /* RSA keys/certs might be allowed by alternate signature types */
+ switch (key->type) {
+ case KEY_RSA:
+- if (match_pattern_list("rsa-sha2-512",
+- options.pubkey_accepted_algos, 0) == 1)
++ if (match_pattern_list("rsa-sha2-512", allowlist, 0) == 1)
+ return 1;
+- if (match_pattern_list("rsa-sha2-256",
+- options.pubkey_accepted_algos, 0) == 1)
++ if (match_pattern_list("rsa-sha2-256", allowlist, 0) == 1)
+ return 1;
+ break;
+ case KEY_RSA_CERT:
+ if (match_pattern_list("[email protected]",
+- options.pubkey_accepted_algos, 0) == 1)
++ allowlist, 0) == 1)
+ return 1;
+ if (match_pattern_list("[email protected]",
+- options.pubkey_accepted_algos, 0) == 1)
++ allowlist, 0) == 1)
+ return 1;
+ break;
+ }
+ return 0;
+ }
+
++static int
++key_type_allowed_by_config(struct sshkey *key)
++{
++ return key_type_allowed(key, options.pubkey_accepted_algos);
++}
++
+ /* obtain a list of keys from the agent */
+ static int
+ get_agent_identities(struct ssh *ssh, int *agent_fdp,
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35388.patch
openssh-9.2p1/debian/patches/CVE-2026-35388.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35388.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35388.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,40 @@
+From 684fbae02b8e85e5f14e978201a3d5b68686d0fd Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:39:57 +0000
+Subject: upstream: add missing askpass check when using
+
+ControlMaster=ask/autoask and "ssh -O proxy ..."; reported by Michalis
+Vasileiadis
+
+OpenBSD-Commit-ID: 8dd7b9b96534e9a8726916b96d36bed466d3836a
+
+Origin: upstream,
https://anongit.mindrot.org/openssh.git/commit/?id=c805b97b67c774e0bf922ffb29dfbcda9d7b5add
+Bug-Debian: https://bugs.debian.org/1132575
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35388.patch
+---
+ mux.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/mux.c b/mux.c
+index e7580ac74..bda4015f4 100644
+--- a/mux.c
++++ b/mux.c
+@@ -1123,6 +1123,16 @@ mux_master_process_proxy(struct ssh *ssh, u_int rid,
+
+ debug_f("channel %d: proxy request", c->self);
+
++ if (options.control_master == SSHCTL_MASTER_ASK ||
++ options.control_master == SSHCTL_MASTER_AUTO_ASK) {
++ if (!ask_permission("Allow multiplex proxy connection?")) {
++ debug2_f("proxy refused by user");
++ reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
++ "Permission denied");
++ return 0;
++ }
++ }
++
+ c->mux_rcb = channel_proxy_downstream;
+ if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 ||
+ (r = sshbuf_put_u32(reply, rid)) != 0)
diff -Nru openssh-9.2p1/debian/patches/CVE-2026-35414.patch
openssh-9.2p1/debian/patches/CVE-2026-35414.patch
--- openssh-9.2p1/debian/patches/CVE-2026-35414.patch 1970-01-01
01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2026-35414.patch 2026-05-03
19:16:45.000000000 +0100
@@ -0,0 +1,79 @@
+From f5daf40e6bcb932a72665c7df03ab4b5e4950e3b Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Thu, 2 Apr 2026 07:48:13 +0000
+Subject: sshd(8): fix inappropriate matching of authorized_keys principals
+
+When matching an authorized_keys principals="" option against a list of
+principals in a certificate, an incorrect algorithm was used that could
+allow inappropriate matching in cases where a principal name in the
+certificate contains a comma character. Exploitation of the condition
+requires an authorized_keys principals="" option that lists more than
+one principal *and* a CA that will issue a certificate that encodes more
+than one of these principal names separated by a comma (typical CAs
+strongly constrain which principal names they will place in a
+certificate). This condition only applies to user- trusted CA keys in
+authorized_keys, the main certificate authentication path
+(TrustedUserCAKeys/AuthorizedPrincipalsFile) is not affected.
+
+Reported by Vladimir Tokarev.
+
+OpenBSD-Commit-ID: c790e2687c35989ae34a00e709be935c55b16a86
+
+[cjwatson: Committed upstream together with apparently-unrelated changes
+for CVE-2026-35387. I've split them into separate patches for clarity.]
+
+Origin: backport,
https://anongit.mindrot.org/openssh.git/commit/?id=fd1c7e131f331942d20f42f31e79912d570081fa
+Bug-Debian: https://bugs.debian.org/1132576
+Last-Update: 2026-05-03
+
+Patch-Name: CVE-2026-35414.patch
+---
+ auth2-pubkeyfile.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/auth2-pubkeyfile.c b/auth2-pubkeyfile.c
+index 0cfacac35..6b757e55b 100644
+--- a/auth2-pubkeyfile.c
++++ b/auth2-pubkeyfile.c
+@@ -51,6 +51,7 @@
+ #include "authfile.h"
+ #include "match.h"
+ #include "ssherr.h"
++#include "xmalloc.h"
+
+ int
+ auth_authorise_keyopts(struct passwd *pw, struct sshauthopt *opts,
+@@ -147,20 +148,23 @@ auth_authorise_keyopts(struct passwd *pw, struct
sshauthopt *opts,
+ static int
+ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
+ {
+- char *result;
++ char *list, *olist, *entry;
+ u_int i;
+
+- /* XXX percent_expand() sequences for authorized_principals? */
+-
+- for (i = 0; i < cert->nprincipals; i++) {
+- if ((result = match_list(cert->principals[i],
+- principal_list, NULL)) != NULL) {
+- debug3("matched principal from key options \"%.100s\"",
+- result);
+- free(result);
+- return 1;
++ olist = list = xstrdup(principal_list);
++ for (;;) {
++ if ((entry = strsep(&list, ",")) == NULL || *entry == '\0')
++ break;
++ for (i = 0; i < cert->nprincipals; i++) {
++ if (strcmp(entry, cert->principals[i]) == 0) {
++ debug3("matched principal from key i"
++ "options \"%.100s\"", entry);
++ free(olist);
++ return 1;
++ }
+ }
+ }
++ free(olist);
+ return 0;
+ }
+
diff -Nru openssh-9.2p1/debian/patches/prohibit-comma-in-hostnames.patch
openssh-9.2p1/debian/patches/prohibit-comma-in-hostnames.patch
--- openssh-9.2p1/debian/patches/prohibit-comma-in-hostnames.patch
1970-01-01 01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/prohibit-comma-in-hostnames.patch
2026-05-03 19:16:45.000000000 +0100
@@ -0,0 +1,30 @@
+From 89b8a38abd917937a44bcf1394d0c1e6641efc76 Mon Sep 17 00:00:00 2001
+From: "[email protected]" <[email protected]>
+Date: Fri, 21 Feb 2025 18:22:41 +0000
+Subject: upstream: Also prohibit , (comma) in hostnames, proposed by David
+
+Leadbeater ok djm millert
+
+OpenBSD-Commit-ID: 2837fa31dc6e81976f510f0a259edaa559b20b07
+
+Origin: upstream,
https://anongit.mindrot.org/openssh.git/commit/?id=487cf4c18c123b66c1f3f733398cd37e6b2ab6ab
+Last-Update: 2026-05-03
+
+Patch-Name: prohibit-comma-in-hostnames.patch
+---
+ ssh.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ssh.c b/ssh.c
+index a45da5877..a0371839b 100644
+--- a/ssh.c
++++ b/ssh.c
+@@ -631,7 +631,7 @@ valid_hostname(const char *s)
+ if (*s == '-')
+ return 0;
+ for (i = 0; s[i] != 0; i++) {
+- if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL ||
++ if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL ||
+ isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
+ return 0;
+ }
diff -Nru openssh-9.2p1/debian/patches/series
openssh-9.2p1/debian/patches/series
--- openssh-9.2p1/debian/patches/series 2026-04-05 00:33:20.000000000 +0100
+++ openssh-9.2p1/debian/patches/series 2026-05-03 19:16:45.000000000 +0100
@@ -43,3 +43,11 @@
CVE-2025-61984.patch
CVE-2025-61985.patch
CVE-2025-61984-tests.patch
+CVE-2026-35388.patch
+CVE-2026-35385.patch
+CVE-2026-35387.patch
+CVE-2026-35414.patch
+prohibit-comma-in-hostnames.patch
+CVE-2026-35386-1.patch
+CVE-2026-35386-2.patch
+CVE-2026-35386-3.patch
--- End Message ---