--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:proftpd-dfsg
User: [email protected]
Usertags: pu
(Please provide enough information to help the release team
to judge the request efficiently. E.g. by filling in the
sections below.)
[ Reason ]
The bug is described in the description CVE-2026-42167.
The bug was introduced in
https://github.com/proftpd/proftpd/commit/86bdcf597fb8b1f820c77aabb6cc61a1ac9bb0a7
[ Impact ]
Users are impacted CVE-2026-42167.
https://app.opencve.io/cve/CVE-2026-42167
The CVSS score of 8.1 indicates a high severity risk. No EPSS
score is available, so the current exploration probability is
unknown; however, the exploit requires specific configuration
conditions (mod_sql enabled, %U logging, and a permissive SQL
backend). The vulnerability is not listed in CISA’s KEV catalog,
but its remote nature and the straightforward input vector make
it an attractive target for attackers. If the conditions are
met, an attacker can execute arbitrary commands on the host
without needing additional privileges.
[ Tests ]
The proftp package has a test suite, which was executed
successfully.
[ Risks ]
The core of the patch looks rather trivial. Some more variables
(which are supplied by the end user) are escaped.
[ 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
[ Changes ]
The debdiff contains the patch for CVE-2026-42167 adapted for
proftp 1.3.8c.
Version in base suite: 1.3.8.c+dfsg-4+deb13u1
Base version: proftpd-dfsg_1.3.8.c+dfsg-4+deb13u1
Target version: proftpd-dfsg_1.3.8.c+dfsg-4+deb13u2
Base file:
/srv/ftp-master.debian.org/ftp/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u1.dsc
Target file:
/srv/ftp-master.debian.org/policy/pool/main/p/proftpd-dfsg/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u2.dsc
changelog | 7 +
patches/2052_pghmcfc.diff | 195 ++++++++++++++++++++++++++++++++++++++++++++++
patches/series | 1
3 files changed, 203 insertions(+)
dpkg-source: warning: cannot verify inline signature for
/srv/release.debian.org/tmp/tmppina8tr8/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u1.dsc:
no acceptable signature found
dpkg-source: warning: cannot verify inline signature for
/srv/release.debian.org/tmp/tmppina8tr8/proftpd-dfsg_1.3.8.c+dfsg-4+deb13u2.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 2025-11-09 13:49:42.000000000
+0000
+++ proftpd-dfsg-1.3.8.c+dfsg/debian/changelog 2026-05-01 10:48:15.000000000
+0000
@@ -1,3 +1,10 @@
+proftpd-dfsg (1.3.8.c+dfsg-4+deb13u2) trixie; urgency=medium
+
+ * Add patch for CVE-2026-42167 (Closes: #1135119).
+ Thanks to Paul Howarth for adaption to 1.3.8c.
+
+ -- Hilmar Preuße <[email protected]> Fri, 01 May 2026 12:48:15 +0200
+
proftpd-dfsg (1.3.8.c+dfsg-4+deb13u1) trixie; urgency=medium
[ Evgeni Golov <[email protected]> ]
diff -Nru proftpd-dfsg-1.3.8.c+dfsg/debian/patches/2052_pghmcfc.diff
proftpd-dfsg-1.3.8.c+dfsg/debian/patches/2052_pghmcfc.diff
--- proftpd-dfsg-1.3.8.c+dfsg/debian/patches/2052_pghmcfc.diff 1970-01-01
00:00:00.000000000 +0000
+++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/2052_pghmcfc.diff 2026-05-01
10:47:52.000000000 +0000
@@ -0,0 +1,195 @@
+From 415395b795436ae47cc25b2394e80033b80f11be Mon Sep 17 00:00:00 2001
+From: TJ Saunders <[email protected]>
+Date: Mon, 27 Apr 2026 12:13:09 -0700
+Subject: [PATCH] Issue #2052: When resolving any variable whose value is
+ supplied by the client, make sure we **always** escape that value text.
+
+---
+ contrib/mod_sql.c | 103 ++++++++++++++++++++++++++++------------------
+ 1 file changed, 64 insertions(+), 39 deletions(-)
+
+diff --git a/contrib/mod_sql.c b/contrib/mod_sql.c
+index 4978b38b70..4872f5fa64 100644
+--- a/contrib/mod_sql.c
++++ b/contrib/mod_sql.c
+@@ -2,7 +2,7 @@
+ * ProFTPD: mod_sql -- SQL frontend
+ * Copyright (c) 1998-1999 Johnie Ingram.
+ * Copyright (c) 2001 Andrew Houghton.
+- * Copyright (c) 2004-2022 TJ Saunders
++ * Copyright (c) 2004-2026 TJ Saunders
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -760,40 +760,46 @@ static int is_escaped_text(const char *text, size_t
text_len) {
+ }
+
+ static int sql_resolved_append_text(pool *p, struct sql_resolved *resolved,
+- const char *text, size_t text_len) {
+- char *new_text;
+- size_t new_textlen;
++ const char *text, size_t text_len, int already_escaped) {
++ char *new_text = NULL;
++ size_t new_textlen = 0;
+
+ if (text == NULL ||
+ text_len == 0) {
+ return 0;
+ }
+
+- /* For backward compatibility (see Issue #1149), we indulge in a little
+- * heuristic here, and only escape the text if it hasn't already been
+- * escaped. How to properly tell? If the first and last characters of
+- * the given text are `'`, AND there are no other occurrences of that
+- * character in the text, assume it has already been quoted.
+- */
+- if (is_escaped_text(text, text_len) == FALSE) {
+- modret_t *mr;
++ new_text = (char *) text;
++ new_textlen = text_len;
+
+- mr = sql_dispatch(sql_make_cmd(p, 2, resolved->conn_name, text),
+- "sql_escapestring");
+- if (check_response(mr, resolved->conn_flags) < 0) {
+- errno = EIO;
+- return -1;
+- }
++ if (already_escaped == FALSE) {
++ /* For backward compatibility (see Issue #1149), we indulge in a little
++ * heuristic here, and only escape the text if it hasn't already been
++ * escaped. How to properly tell? If the first and last characters of
++ * the given text are `'`, AND there are no other occurrences of that
++ * character in the text, assume it has already been quoted.
++ *
++ * Per Issue #2052, we refine this to use this heuristic only if we do
++ * not already know that the text has been escaped. Some callers may
++ * have already escaped the provided text for us.
++ */
++ if (is_escaped_text(text, text_len) == FALSE) {
++ modret_t *mr;
+
+- new_text = (char *) mr->data;
+- new_textlen = strlen(new_text);
++ mr = sql_dispatch(sql_make_cmd(p, 2, resolved->conn_name, text),
++ "sql_escapestring");
++ if (check_response(mr, resolved->conn_flags) < 0) {
++ errno = EIO;
++ return -1;
++ }
+
+- } else {
+- pr_trace_msg(trace_channel, 17,
+- "text '%s' is already escaped, skipping escaping it again", text);
++ new_text = (char *) mr->data;
++ new_textlen = strlen(new_text);
+
+- new_text = (char *) text;
+- new_textlen = text_len;
++ } else {
++ pr_trace_msg(trace_channel, 17,
++ "text '%s' is already escaped, skipping escaping it again", text);
++ }
+ }
+
+ if (new_textlen > resolved->buflen) {
+@@ -811,7 +817,7 @@ static int sql_resolved_append_text(pool *p, struct
sql_resolved *resolved,
+
+ static int sql_resolve_on_meta(pool *p, pr_jot_ctx_t *jot_ctx,
+ unsigned char logfmt_id, const char *jot_hint, const void *val) {
+- int res = 0;
++ int res = 0, already_escaped = FALSE;
+ struct sql_resolved *resolved;
+
+ resolved = jot_ctx->log;
+@@ -970,35 +976,53 @@ static int sql_resolve_on_meta(pool *p, pr_jot_ctx_t
*jot_ctx,
+ break;
+ }
+
++ /* Per Issue #2052, the following variable values can all be supplied
++ * remotely by the client. As such, they should be escaped
preemptively.
++ */
+ case LOGFMT_META_ANON_PASS:
+ case LOGFMT_META_BASENAME:
+- case LOGFMT_META_CLASS:
+ case LOGFMT_META_CMD_PARAMS:
+ case LOGFMT_META_COMMAND:
+ case LOGFMT_META_DIR_NAME:
+ case LOGFMT_META_DIR_PATH:
++ case LOGFMT_META_FILENAME:
++ case LOGFMT_META_IDENT_USER:
++ case LOGFMT_META_METHOD:
++ case LOGFMT_META_ORIGINAL_USER:
++ case LOGFMT_META_RESPONSE_STR:
++ case LOGFMT_META_REMOTE_HOST:
++ case LOGFMT_META_RENAME_FROM:
++ case LOGFMT_META_USER:
++ case LOGFMT_META_XFER_PATH: {
++ modret_t *mr;
++
++ mr = sql_dispatch(sql_make_cmd(p, 2, resolved->conn_name,
++ (const char *) val), "sql_escapestring");
++ if (check_response(mr, resolved->conn_flags) < 0) {
++ errno = EIO;
++ return -1;
++ }
++
++ text = (char *) mr->data;
++ text_len = strlen(text);
++ already_escaped = TRUE;
++ break;
++ }
++
++ case LOGFMT_META_CLASS:
+ case LOGFMT_META_ENV_VAR:
+ case LOGFMT_META_EOS_REASON:
+- case LOGFMT_META_FILENAME:
+ case LOGFMT_META_GROUP:
+- case LOGFMT_META_IDENT_USER:
+ case LOGFMT_META_ISO8601:
+ case LOGFMT_META_LOCAL_FQDN:
+ case LOGFMT_META_LOCAL_IP:
+ case LOGFMT_META_LOCAL_NAME:
+- case LOGFMT_META_METHOD:
+ case LOGFMT_META_NOTE_VAR:
+- case LOGFMT_META_ORIGINAL_USER:
+ case LOGFMT_META_PROTOCOL:
+- case LOGFMT_META_REMOTE_HOST:
+ case LOGFMT_META_REMOTE_IP:
+- case LOGFMT_META_RENAME_FROM:
+- case LOGFMT_META_RESPONSE_STR:
+- case LOGFMT_META_USER:
+ case LOGFMT_META_VERSION:
+ case LOGFMT_META_VHOST_IP:
+ case LOGFMT_META_XFER_FAILURE:
+- case LOGFMT_META_XFER_PATH:
+ case LOGFMT_META_XFER_STATUS:
+ case LOGFMT_META_XFER_TYPE:
+ default:
+@@ -1011,7 +1035,8 @@ static int sql_resolve_on_meta(pool *p, pr_jot_ctx_t
*jot_ctx,
+ text_len = strlen(text);
+ }
+
+- res = sql_resolved_append_text(p, resolved, text, text_len);
++ res = sql_resolved_append_text(p, resolved, text, text_len,
++ already_escaped);
+ }
+
+ return res;
+@@ -1074,7 +1099,7 @@ static int sql_resolve_on_default(pool *p, pr_jot_ctx_t
*jot_ctx,
+ break;
+ }
+
+- res = sql_resolved_append_text(p, resolved, text, text_len);
++ res = sql_resolved_append_text(p, resolved, text, text_len, FALSE);
+ }
+
+ return res;
+@@ -3175,7 +3200,7 @@ static int showinfo_on_meta(pool *p, pr_jot_ctx_t
*jot_ctx,
+ }
+
+ text_len = strlen(text);
+- res = sql_resolved_append_text(p, resolved, text, text_len);
++ res = sql_resolved_append_text(p, resolved, text, text_len, FALSE);
+
+ } else {
+ res = sql_resolve_on_meta(p, jot_ctx, logfmt_id, jot_hint, val);
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 2025-11-09
13:48:21.000000000 +0000
+++ proftpd-dfsg-1.3.8.c+dfsg/debian/patches/series 2026-05-01
10:47:52.000000000 +0000
@@ -20,3 +20,4 @@
e7539bd772ca6e12d3e05fb56da274cf78ee1edf.diff
14c006b62c09d1efe302c57b2d183a489bcb22dc.diff
9b2b4a3e32d251798bf8fa841b124ab15ba58f11.diff
+2052_pghmcfc.diff
signature.asc
Description: PGP signature
--- End Message ---