Version in base suite: 1.3.8.c+dfsg-4+deb13u3 Version in overlay suite: 1.3.8.c+dfsg-4+deb13u4 Base version: proftpd-dfsg_1.3.8.c+dfsg-4+deb13u4 Target version: proftpd-dfsg_1.3.8.c+dfsg-4+deb13u5 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u4.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u5.dsc changelog | 6 patches/1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff | 76 +++++++++++ patches/4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff | 55 ++++++++ patches/ab5c8cd35f85b75e90019a32674a1f1062268bec.diff | 115 ++++++++++++++++++ patches/series | 6 5 files changed, 258 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpb5vj5_x7/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u4.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpb5vj5_x7/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u5.dsc: no acceptable signature found diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/changelog proftpd-dfsg-1.3.8.c+dfsg/debian/changelog --- proftpd-dfsg-1.3.8.c+dfsg/debian/changelog 2026-10-25 21:16:31.000000000 +0000 +++ proftpd-dfsg-1.3.8.c+dfsg/debian/changelog 2026-11-06 21:43:56.000000000 +0000 @@ -1,3 +1,9 @@ +proftpd-dfsg (1.3.8.c+dfsg-4+deb13u5) trixie; urgency=medium + + * Add patches for CVE-2026-119147, CVE-2026-119146 & CVE-2026-119364 . + + -- Hilmar Preuße Fri, 06 Nov 2026 22:43:56 +0100 + proftpd-dfsg (1.3.8.c+dfsg-4+deb13u4) trixie; urgency=medium * Add patches for mod_tls spins at 100% CPU (...) (Closes: #1151962). diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/patches/1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff proftpd-dfsg-1.3.8.c+dfsg/debian/patches/1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff --- proftpd-dfsg-1.3.8.c+dfsg/debian/patches/1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff 1970-01-01 00:00:00.000000000 +0000 +++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff 2026-11-06 21:39:33.000000000 +0000 @@ -0,0 +1,76 @@ +From 1570fd3b7a70b447bd59b175ed7fb01fb3d8242b Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Wed, 21 Oct 2026 10:49:06 -0700 +Subject: [PATCH] When an authenticated user invokes the SFTP "copy-file" + extension and the destination does not exist, mod_sftp performs the copy + without checking some policies, allowing for file creation in directories + denied by ``. + +Thanks to Abraxas Labs and MiniMax Security for reporting this issue. +--- + contrib/mod_sftp/fxp.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +--- proftpd.orig/contrib/mod_sftp/fxp.c ++++ proftpd/contrib/mod_sftp/fxp.c +@@ -4681,29 +4681,22 @@ + res = pr_fsio_stat(dst, &st); + if (res == 0) { + unsigned char *allow_overwrite = NULL; +- int limit_allow; + + allow_overwrite = get_param_ptr(get_dir_ctxt(fxp->pool, dst), + "AllowOverwrite", FALSE); + + cmd2 = pr_cmd_alloc(fxp->pool, 3, "SITE_COPY", src, dst); + cmd2->arg = pstrdup(fxp->pool, args); +- limit_allow = dir_check(fxp->pool, cmd2, "WRITE", dst, NULL); + + if (!overwrite || + (allow_overwrite == NULL || +- *allow_overwrite == FALSE) || +- !limit_allow) { ++ *allow_overwrite == FALSE)) { + xerrno = EACCES; + + if (!overwrite) { + (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, + "'%s' exists and client did not request COPY overwrites", dst); + +- } else if (!limit_allow) { +- (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, +- "COPY to '%s' blocked by configuration", dst); +- + } else { + (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, + "AllowOverwrite permission denied for '%s'", dst); +@@ -4764,6 +4757,29 @@ + + fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code, + reason, NULL); ++ ++ fxp_cmd_dispatch_err(cmd); ++ ++ resp = fxp_packet_create(fxp->pool, fxp->channel_id); ++ resp->payload = ptr; ++ resp->payload_sz = (bufsz - buflen); ++ ++ return fxp_packet_write(resp); ++ } ++ ++ if (!dir_check(fxp->pool, cmd2, "WRITE", dst, NULL)) { ++ xerrno = EACCES; ++ ++ (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, ++ "COPY to '%s' blocked by configuration", dst); ++ ++ status_code = fxp_errno2status(xerrno, &reason); ++ ++ pr_trace_msg(trace_channel, 8, "sending response: STATUS %lu '%s'", ++ (unsigned long) status_code, reason); ++ ++ fxp_status_write(fxp->pool, &buf, &buflen, fxp->request_id, status_code, ++ reason, NULL); + + fxp_cmd_dispatch_err(cmd); + diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/patches/4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff proftpd-dfsg-1.3.8.c+dfsg/debian/patches/4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff --- proftpd-dfsg-1.3.8.c+dfsg/debian/patches/4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff 1970-01-01 00:00:00.000000000 +0000 +++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff 2026-11-06 21:39:33.000000000 +0000 @@ -0,0 +1,55 @@ +From 4bafd1e9861506e77b9ea3ed277b58e60eacfe4d Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 6 Sep 2026 14:51:15 -0700 +Subject: [PATCH] Guard against overly-long keys overflowing buffers when the + "utf8trans" builtin `RewriteMap` type is used. + +Thanks to Bruno Henc for reporting this issue. +--- + contrib/mod_rewrite.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +--- proftpd.orig/contrib/mod_rewrite.c ++++ proftpd/contrib/mod_rewrite.c +@@ -1634,9 +1634,10 @@ + */ + static int rewrite_utf8_to_ucs4(unsigned long *ucs4_buf, + size_t utf8_len, unsigned char *utf8_buf) { +- const unsigned char *utf8_endbuf = utf8_buf + utf8_len; ++ const unsigned char *utf8_endbuf; + int ucs_len = 0; + ++ utf8_endbuf = utf8_buf + utf8_len; + while (utf8_buf != utf8_endbuf) { + pr_signals_handle(); + +@@ -2003,13 +2004,27 @@ + } + + static char *rewrite_map_int_utf8trans(pool *map_pool, char *key) { +- int ucs4strlen = 0; + static unsigned char utf8_val[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; + static unsigned long ucs4_longs[PR_TUNABLE_BUFFER_SIZE] = {0L}; ++ int ucs4strlen = 0; ++ size_t key_len = 0; + + /* If the key is NULL or empty, do nothing. */ ++ if (key != NULL) { ++ key_len = strlen(key); ++ } ++ + if (key == NULL || +- strlen(key) == 0) { ++ key_len == 0) { ++ return NULL; ++ } ++ ++ /* If the key length exceeds our buffers, reject it. */ ++ if (key_len >= sizeof(utf8_val)) { ++ rewrite_log("utf8trans: key '%.100s...' length (%lu bytes) exceeds " ++ "maximum allowed length (%lu bytes), rejecting", key, ++ (unsigned long) key_len, (unsigned long) sizeof(utf8_val)); ++ errno = EPERM; + return NULL; + } + diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/patches/ab5c8cd35f85b75e90019a32674a1f1062268bec.diff proftpd-dfsg-1.3.8.c+dfsg/debian/patches/ab5c8cd35f85b75e90019a32674a1f1062268bec.diff --- proftpd-dfsg-1.3.8.c+dfsg/debian/patches/ab5c8cd35f85b75e90019a32674a1f1062268bec.diff 1970-01-01 00:00:00.000000000 +0000 +++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/ab5c8cd35f85b75e90019a32674a1f1062268bec.diff 2026-11-06 21:39:33.000000000 +0000 @@ -0,0 +1,115 @@ +From ab5c8cd35f85b75e90019a32674a1f1062268bec Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sat, 17 Oct 2026 13:12:56 -0700 +Subject: [PATCH] Issue #2374: Resolve the destination path in order to handle + any potential symlinks, and use the resolved path for checks. + +--- + contrib/mod_copy.c | 51 +++++++++++++++++++++++++++++++++++----------- + 1 file changed, 39 insertions(+), 12 deletions(-) + +--- proftpd.orig/contrib/mod_copy.c ++++ proftpd/contrib/mod_copy.c +@@ -610,7 +610,29 @@ + return PR_ERROR(cmd); + } + +- to = dir_canonical_vpath(cmd->tmp_pool, decoded_path); ++ pr_fs_clear_cache2(decoded_path); ++ to = dir_realpath(cmd->tmp_pool, decoded_path); ++ if (to == NULL) { ++ /* Try using dir_best_path(), as xfer_pre_stor() does. */ ++ to = dir_best_path(cmd->tmp_pool, decoded_path); ++ } ++ ++ cmd_name = cmd->argv[0]; ++ pr_cmd_set_name(cmd, "SITE_COPY"); ++ if (!dir_check(cmd->tmp_pool, cmd, G_READ, from, NULL)) { ++ int xerrno = EPERM; ++ ++ pr_cmd_set_name(cmd, cmd_name); ++ pr_log_debug(DEBUG8, "%s %s %s denied by configuration", ++ (char *) cmd->argv[0], (char *) cmd->argv[1], from); ++ pr_response_add_err(R_550, "%s: %s", (char *) cmd->argv[2], ++ strerror(xerrno)); ++ ++ pr_cmd_set_errno(cmd, xerrno); ++ errno = xerrno; ++ return PR_ERROR(cmd); ++ } ++ pr_cmd_set_name(cmd, cmd_name); + + cmd_name = cmd->argv[0]; + pr_cmd_set_name(cmd, "SITE_COPY"); +@@ -618,8 +640,8 @@ + int xerrno = EPERM; + + pr_cmd_set_name(cmd, cmd_name); +- pr_log_debug(DEBUG8, "%s denied by configuration", +- (char *) cmd->argv[0]); ++ pr_log_debug(DEBUG8, "%s %s %s denied by configuration", ++ (char *) cmd->argv[0], (char *) cmd->argv[1], to); + pr_response_add_err(R_550, "%s: %s", (char *) cmd->argv[3], + strerror(xerrno)); + +@@ -776,7 +798,7 @@ + + MODRET copy_cpto(cmd_rec *cmd) { + register unsigned int i; +- const char *from, *to = ""; ++ const char *from, *to = "", *resolved_to; + char *cmd_name; + unsigned char *authenticated = NULL; + +@@ -834,16 +856,21 @@ + to = pstrcat(cmd->tmp_pool, to, *to ? " " : "", decoded_path, NULL); + } + +- to = dir_canonical_vpath(cmd->tmp_pool, to); ++ pr_fs_clear_cache2(to); ++ resolved_to = dir_realpath(cmd->tmp_pool, to); ++ if (resolved_to == NULL) { ++ /* Try using dir_best_path(), as xfer_pre_stor() does. */ ++ resolved_to = dir_best_path(cmd->tmp_pool, to); ++ } + + cmd_name = cmd->argv[0]; + pr_cmd_set_name(cmd, "SITE_CPTO"); +- if (!dir_check(cmd->tmp_pool, cmd, G_WRITE, to, NULL)) { ++ if (!dir_check(cmd->tmp_pool, cmd, G_WRITE, resolved_to, NULL)) { + int xerrno = EPERM; + + pr_cmd_set_name(cmd, cmd_name); +- pr_log_debug(DEBUG8, "%s denied by configuration", +- (char *) cmd->argv[0]); ++ pr_log_debug(DEBUG8, "%s %s %s denied by configuration", ++ (char *) cmd->argv[0], (char *) cmd->argv[1], to); + pr_response_add_err(R_550, "%s: %s", to, strerror(xerrno)); + + pr_cmd_set_errno(cmd, xerrno); +@@ -852,12 +879,12 @@ + } + pr_cmd_set_name(cmd, cmd_name); + +- if (copy_paths(cmd->tmp_pool, from, to) < 0) { ++ if (copy_paths(cmd->tmp_pool, from, resolved_to) < 0) { + int xerrno = errno; + const char *err_code = R_550; + + pr_log_debug(DEBUG7, MOD_COPY_VERSION +- ": error copying '%s' to '%s': %s", from, to, strerror(xerrno)); ++ ": error copying '%s' to '%s': %s", from, resolved_to, strerror(xerrno)); + + /* Check errno for EDQOUT (or the most appropriate alternative). + * (I hate the fact that FTP has a special response code just for +@@ -882,8 +909,8 @@ + break; + } + +- pr_response_add_err(err_code, "%s: %s", (char *) cmd->argv[1], +- strerror(xerrno)); ++ pr_response_add_err(err_code, "%s %s: %s", (char *) cmd->argv[0], ++ (char *) cmd->argv[1], strerror(xerrno)); + + pr_cmd_set_errno(cmd, xerrno); + errno = xerrno; diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/patches/series proftpd-dfsg-1.3.8.c+dfsg/debian/patches/series --- proftpd-dfsg-1.3.8.c+dfsg/debian/patches/series 2026-10-25 12:35:05.000000000 +0000 +++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/series 2026-11-06 21:39:33.000000000 +0000 @@ -35,3 +35,9 @@ 508eb4d1b8c550b5f3059ad5b33d60c6b6c76bc7.diff # Debian #1151962 #3 Issue #2093 (PR #2094) c1607a2a219d56443809de326e673b4e38b3bc58.diff +# CVE-2026-119147 +1570fd3b7a70b447bd59b175ed7fb01fb3d8242b.diff +# CVE-2026-119146 +4bafd1e9861506e77b9ea3ed277b58e60eacfe4d.diff +# CVE-2026-119364 +ab5c8cd35f85b75e90019a32674a1f1062268bec.diff