new file mode 100644
@@ -0,0 +1,276 @@
+From 361d797281f7ecfce4c2fb642c40227d66e541b5 Mon Sep 17 00:00:00 2001
+From: Changqing Li <changqing.li@windriver.com>
+Date: Tue, 21 Apr 2026 17:10:37 +0800
+Subject: [PATCH] Fix CVE-2026-1467
+
+CVE: CVE-2026-1467
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/6dfe506618d2d5856618e5c0f85bd93386dc8012]
+
+The original backport patch targets libsoup3. This patch has been
+adapted accordingly for libsoup2, refer the openSUSE patch, see [1]
+
+[1] https://www.suse.com/security/cve/CVE-2026-1467.html
+
+Signed-off-by: Changqing Li <changqing.li@windriver.com>
+
+Update soup_session_connect_async(...) in soup-session.c to handle
+the case where soup_message_new_from_uri() fails and returns a NULL
+msg. Adjust connection unit tests to account for the change in
+soup_session_connect_async(...).
+
+Backport the uri-parsing uri validation unit tests from the upstream
+libsoup3 patch
+
+Signed-off-by: Jason Stasiak <jason.stasiak@gmail.com>
+---
+ libsoup/soup-auth.c | 2 +-
+ libsoup/soup-message.c | 5 +++-
+ libsoup/soup-session.c | 13 +++++++++
+ libsoup/soup-uri.c | 60 ++++++++++++++++++++++++++++++++++++++++
+ libsoup/soup-uri.h | 2 ++
+ tests/connection-test.c | 8 ++++--
+ tests/uri-parsing-test.c | 41 +++++++++++++++++++++++++++
+ 7 files changed, 127 insertions(+), 4 deletions(-)
+
+diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c
+index 1896aab7..e205fe31 100644
+--- a/libsoup/soup-auth.c
++++ b/libsoup/soup-auth.c
+@@ -535,7 +535,7 @@ GSList *
+ soup_auth_get_protection_space (SoupAuth *auth, SoupURI *source_uri)
+ {
+ g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
+- g_return_val_if_fail (source_uri != NULL, NULL);
++ g_return_val_if_fail (soup_uri_is_valid (source_uri), NULL);
+
+ return SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri);
+ }
+diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
+index da32b42f..cc4f22b6 100644
+--- a/libsoup/soup-message.c
++++ b/libsoup/soup-message.c
+@@ -1044,7 +1044,7 @@ soup_message_new (const char *method, const char *uri_string)
+ uri = soup_uri_new (uri_string);
+ if (!uri)
+ return NULL;
+- if (!uri->host) {
++ if (!soup_uri_is_valid (uri)) {
+ soup_uri_free (uri);
+ return NULL;
+ }
+@@ -1066,6 +1066,8 @@ soup_message_new (const char *method, const char *uri_string)
+ SoupMessage *
+ soup_message_new_from_uri (const char *method, SoupURI *uri)
+ {
++ g_return_val_if_fail (soup_uri_is_valid (uri), NULL);
++
+ return g_object_new (SOUP_TYPE_MESSAGE,
+ SOUP_MESSAGE_METHOD, method,
+ SOUP_MESSAGE_URI, uri,
+@@ -1676,6 +1678,7 @@ soup_message_set_uri (SoupMessage *msg, SoupURI *uri)
+ SoupMessagePrivate *priv;
+
+ g_return_if_fail (SOUP_IS_MESSAGE (msg));
++ g_return_if_fail (soup_uri_is_valid (uri));
+ priv = soup_message_get_instance_private (msg);
+
+ if (priv->uri)
+diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
+index 4472bb91..fadd5cd2 100644
+--- a/libsoup/soup-session.c
++++ b/libsoup/soup-session.c
+@@ -5106,6 +5106,7 @@ soup_session_connect_async (SoupSession *session,
+ SoupMessageQueueItem *item;
+ ConnectAsyncData *data;
+ GTask *task;
++ GError *error = NULL;
+
+ g_return_if_fail (SOUP_IS_SESSION (session));
+ g_return_if_fail (!SOUP_IS_SESSION_SYNC (session));
+@@ -5116,6 +5117,18 @@ soup_session_connect_async (SoupSession *session,
+ task = g_task_new (session, cancellable, callback, user_data);
+
+ msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri);
++
++ /* Trigger task to notify caller when soup_message can not be constructed */
++ if ( msg == NULL ) {
++ g_set_error( &error,
++ G_IO_ERROR,
++ G_IO_ERROR_INVALID_ARGUMENT,
++ "Failed to construct soup message from uri");
++ g_task_return_error (task, error);
++ g_object_unref (task);
++ return;
++ }
++
+ soup_message_set_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
+ g_signal_connect_object (msg, "finished",
+ G_CALLBACK (connect_async_message_finished),
+diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c
+index bdb7a175..d781ff11 100644
+--- a/libsoup/soup-uri.c
++++ b/libsoup/soup-uri.c
+@@ -1342,6 +1342,66 @@ soup_uri_host_equal (gconstpointer v1, gconstpointer v2)
+ return g_ascii_strcasecmp (one->host, two->host) == 0;
+ }
+
++static gboolean
++is_valid_character_for_host (char c)
++{
++ static const char forbidden_chars[] = { '\t', '\n', '\r', ' ', '#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|' };
++ int i;
++
++ for (i = 0; i < G_N_ELEMENTS (forbidden_chars); ++i) {
++ if (c == forbidden_chars[i])
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++static gboolean
++is_host_valid (const char* host)
++{
++ int i;
++ gboolean is_valid;
++ char *ascii_host = NULL;
++
++ if (!host || !host[0])
++ return FALSE;
++
++ if (g_hostname_is_non_ascii (host)) {
++ ascii_host = g_hostname_to_ascii (host);
++ if (!ascii_host)
++ return FALSE;
++
++ host = ascii_host;
++ }
++
++ if ((g_ascii_isdigit (host[0]) || strchr (host, ':')) && g_hostname_is_ip_address (host)) {
++ g_free (ascii_host);
++ return TRUE;
++ }
++ is_valid = TRUE;
++ for (i = 0; host[i] && is_valid; i++)
++ is_valid = is_valid_character_for_host (host[i]);
++
++ g_free (ascii_host);
++
++ return is_valid;
++}
++
++gboolean
++soup_uri_is_valid (SoupURI *uri)
++{
++ if (!uri)
++ return FALSE;
++
++ if (!is_host_valid (soup_uri_get_host (uri)))
++ return FALSE;
++
++ /* FIXME: validate other URI components? */
++
++ return TRUE;
++}
++
++
+ gboolean
+ soup_uri_is_http (SoupURI *uri, char **aliases)
+ {
+diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h
+index 8015e4f1..64099c3c 100644
+--- a/libsoup/soup-uri.h
++++ b/libsoup/soup-uri.h
+@@ -133,6 +133,8 @@ guint soup_uri_host_hash (gconstpointer key);
+ SOUP_AVAILABLE_IN_2_28
+ gboolean soup_uri_host_equal (gconstpointer v1,
+ gconstpointer v2);
++SOUP_AVAILABLE_IN_2_68
++gboolean soup_uri_is_valid (SoupURI *uri);
+
+ #define SOUP_URI_IS_VALID(uri) ((uri) && (uri)->scheme && (uri)->path)
+ #define SOUP_URI_VALID_FOR_HTTP(uri) ((uri) && ((uri)->scheme == SOUP_URI_SCHEME_HTTP || (uri)->scheme == SOUP_URI_SCHEME_HTTPS) && (uri)->host && (uri)->path)
+diff --git a/tests/connection-test.c b/tests/connection-test.c
+index 08400fb9..21ffd6f9 100644
+--- a/tests/connection-test.c
++++ b/tests/connection-test.c
+@@ -1135,11 +1135,15 @@ do_connection_connect_test (void)
+ } else
+ debug_printf (1, " wss -- SKIPPING\n");
+
++ g_test_expect_message ("libsoup",
++ G_LOG_LEVEL_CRITICAL,
++ "*soup_message_new_from_uri*assertion*soup_uri_is_valid*failed*");
+ debug_printf (1, " file\n");
+ file_uri = soup_uri_new ("file:///foo/bar");
+ do_one_connection_connect_fail_test (session, file_uri,
+- G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+- "r");
++ G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
++ "");
++ g_test_assert_expected_messages ();
+
+ debug_printf (1, " wrong http (invalid port)\n");
+ wrong_http_uri = soup_uri_new (HTTP_SERVER);
+diff --git a/tests/uri-parsing-test.c b/tests/uri-parsing-test.c
+index 07ef96b2..68a4940d 100644
+--- a/tests/uri-parsing-test.c
++++ b/tests/uri-parsing-test.c
+@@ -575,6 +575,46 @@ test_uri_decode (void)
+ g_free (decoded);
+ }
+
++static struct {
++ const char *host;
++ gboolean valid;
++} valid_tests[] = {
++ { "example.com", TRUE },
++ { "localhost", TRUE },
++ { "127.0.0.1", TRUE },
++ { "::1", TRUE },
++ { "::192.168.0.10", TRUE },
++ { "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", TRUE },
++ { "\xe4\xbe\x8b\xe5\xad\x90.\xe6\xb5\x8b\xe8\xaf\x95", TRUE },
++ { "012x:4567:89AB:cdef:3210:7654:ba98:FeDc", FALSE },
++ { "\texample.com", FALSE },
++ { "example.com\n", FALSE },
++ { "\r\nexample.com", FALSE },
++ { "example .com", FALSE },
++ { "example:com", FALSE },
++ { "exampl<e>.com", FALSE },
++ { "exampl[e].com", FALSE },
++ { "exampl^e.com", FALSE },
++ { "examp|e.com", FALSE },
++};
++
++static void
++do_valid_tests (void)
++{
++ int i;
++
++ for (i = 0; i < G_N_ELEMENTS (valid_tests); ++i) {
++ SoupURI *uri;
++
++ uri = soup_uri_new ("http://example.com/");
++ soup_uri_set_host (uri, valid_tests[i].host);
++
++ g_assert_true (soup_uri_is_valid (uri) == valid_tests[i].valid);
++
++ soup_uri_free (uri);
++ }
++}
++
+ int
+ main (int argc, char **argv)
+ {
+@@ -589,6 +629,7 @@ main (int argc, char **argv)
+ g_test_add_func ("/uri/normalization", do_normalization_tests);
+ g_test_add_func ("/uri/data", do_data_tests);
+ g_test_add_func ("/uri/decode", test_uri_decode);
++ g_test_add_func ("/uri/valid", do_valid_tests);
+
+ ret = g_test_run ();
+
+--
+2.55.0
+
@@ -41,6 +41,7 @@ SRC_URI = "${GNOME_MIRROR}/libsoup/${SHRT_VER}/libsoup-${PV}.tar.xz \
file://CVE-2025-4476.patch \
file://CVE-2025-2784.patch \
file://CVE-2025-4945.patch \
+ file://CVE-2026-1467.patch \
"
SRC_URI[sha256sum] = "e4b77c41cfc4c8c5a035fcdc320c7bc6cfb75ef7c5a034153df1413fa1d92f13"