Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions SPECS/libsoup/CVE-2026-1467.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
From 07b08db35347fedf99f93cb2884702b1c989c96b Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Tue, 3 Feb 2026 13:02:16 +0000
Subject: [PATCH] uri-utils: validate host in soup_uri_is_valid and replace
SOUP_URI_IS_VALID macro; update message/auth call sites; add tests

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport from existing Build 1042199 of https://gitlab.gnome.org/GNOME/libsoup/-/commit/167ef0c6817658c1a089c75c462482209e207db4.patch
---
libsoup/auth/soup-auth.c | 2 +-
libsoup/soup-message.c | 8 ++---
libsoup/soup-uri-utils-private.h | 5 ++-
libsoup/soup-uri-utils.c | 61 ++++++++++++++++++++++++++++++++
tests/uri-parsing-test.c | 46 ++++++++++++++++++++++++
5 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/libsoup/auth/soup-auth.c b/libsoup/auth/soup-auth.c
index d9bf4af..278baa1 100644
--- a/libsoup/auth/soup-auth.c
+++ b/libsoup/auth/soup-auth.c
@@ -643,7 +643,7 @@ GSList *
soup_auth_get_protection_space (SoupAuth *auth, GUri *source_uri)
{
g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL);
- g_return_val_if_fail (SOUP_URI_IS_VALID (source_uri), NULL);
+ g_return_val_if_fail (soup_uri_is_valid (source_uri), NULL);

GUri *source_uri_normalized = soup_uri_copy_with_normalized_flags (source_uri);
GSList *ret = SOUP_AUTH_GET_CLASS (auth)->get_protection_space (auth, source_uri_normalized);
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 2f5b267..77f326a 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -923,7 +923,7 @@ soup_message_new (const char *method, const char *uri_string)
uri = g_uri_parse (uri_string, SOUP_HTTP_URI_FLAGS, NULL);
if (!uri)
return NULL;
- if (!g_uri_get_host (uri)) {
+ if (!soup_uri_is_valid (uri)) {
g_uri_unref (uri);
return NULL;
}
@@ -946,7 +946,7 @@ SoupMessage *
soup_message_new_from_uri (const char *method, GUri *uri)
{
g_return_val_if_fail (method != NULL, NULL);
- g_return_val_if_fail (SOUP_URI_IS_VALID (uri), NULL);
+ g_return_val_if_fail (soup_uri_is_valid (uri), NULL);

return g_object_new (SOUP_TYPE_MESSAGE,
"method", method,
@@ -966,7 +966,7 @@ soup_message_new_from_uri (const char *method, GUri *uri)
SoupMessage *
soup_message_new_options_ping (GUri *base_uri)
{
- g_return_val_if_fail (SOUP_URI_IS_VALID (base_uri), NULL);
+ g_return_val_if_fail (soup_uri_is_valid (base_uri), NULL);

return g_object_new (SOUP_TYPE_MESSAGE,
"method", SOUP_METHOD_OPTIONS,
@@ -2039,7 +2039,7 @@ soup_message_set_uri (SoupMessage *msg, GUri *uri)
GUri *normalized_uri;

g_return_if_fail (SOUP_IS_MESSAGE (msg));
- g_return_if_fail (SOUP_URI_IS_VALID (uri));
+ g_return_if_fail (soup_uri_is_valid (uri));

priv = soup_message_get_instance_private (msg);

diff --git a/libsoup/soup-uri-utils-private.h b/libsoup/soup-uri-utils-private.h
index 3dbdb85..18aa60f 100644
--- a/libsoup/soup-uri-utils-private.h
+++ b/libsoup/soup-uri-utils-private.h
@@ -10,6 +10,9 @@

G_BEGIN_DECLS

+gboolean soup_uri_is_valid (GUri *uri);
+
+
gboolean soup_uri_is_http (GUri *uri);

gboolean soup_uri_is_https (GUri *uri);
@@ -28,6 +31,6 @@ GUri *soup_uri_copy_with_normalized_flags (GUri *uri);

char *soup_uri_get_host_for_headers (GUri *uri);

-#define SOUP_URI_IS_VALID(x) (x && g_uri_get_host(x) && g_uri_get_host(x)[0])
+

G_END_DECLS
diff --git a/libsoup/soup-uri-utils.c b/libsoup/soup-uri-utils.c
index ce9b2a1..d1fe0bd 100644
--- a/libsoup/soup-uri-utils.c
+++ b/libsoup/soup-uri-utils.c
@@ -244,6 +244,67 @@ 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[] = { ' ', '\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 (GUri *uri)
+{
+ if (!uri)
+ return FALSE;
+
+ if (!is_host_valid (g_uri_get_host (uri)))
+ return FALSE;
+
+ /* FIXME: validate other URI components? */
+
+ return TRUE;
+}
+
gboolean
soup_uri_is_https (GUri *uri)
{
diff --git a/tests/uri-parsing-test.c b/tests/uri-parsing-test.c
index 4c16d7e..d949324 100644
--- a/tests/uri-parsing-test.c
+++ b/tests/uri-parsing-test.c
@@ -114,6 +114,50 @@ do_copy_tests (void)
g_uri_unref (copy);

g_uri_unref (uri);
+
+static struct {
+ const char *scheme;
+ const char *host;
+ const char *as_string;
+ gboolean valid;
+} valid_tests[] = {
+ { "http", "example.com", "http://example.com/", TRUE },
+ { "http", "localhost", "http://localhost/", TRUE },
+ { "http", "127.0.0.1", "http://127.0.0.1/", TRUE },
+ { "http", "::1", "http://[::1]/", TRUE },
+ { "http", "::192.168.0.10", "http://[::192.168.0.10]/", TRUE },
+ { "http", "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/", TRUE },
+ { "http", "\xe4\xbe\x8b\xe5\xad\x90.\xe6\xb5\x8b\xe8\xaf\x95", "http://\xe4\xbe\x8b\xe5\xad\x90.\xe6\xb5\x8b\xe8\xaf\x95/", TRUE },
+ { "http", "012x:4567:89AB:cdef:3210:7654:ba98:FeDc", "http://012x:4567:89AB:cdef:3210:7654:ba98:FeDc/", FALSE },
+ { "http", " example.com", "http:// example.com/", FALSE },
+ { "http", "example.com\n", "http://example.com\n/", FALSE },
+ { "http", "\r\nexample.com", "http://\r\nexample.com/", FALSE },
+ { "http", "example .com", "http://example .com/", FALSE },
+ { "http", "example:com", "http://example:com/", FALSE },
+ { "http", "exampl<e>.com", "http://exampl<e>.com/", FALSE },
+ { "http", "exampl[e].com", "http://exampl[e].com/", FALSE },
+ { "http", "exampl^e.com", "http://exampl^e.com/", FALSE },
+ { "http", "examp|e.com", "http://examp|e.com/", FALSE },
+};
+
+static void
+do_valid_tests (void)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (valid_tests); ++i) {
+ GUri *uri;
+ char *uri_str;
+
+ uri = g_uri_build (SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_ENCODED, valid_tests[i].scheme, NULL, valid_tests[i].host, -1, "", NULL, NULL);
+ uri_str = g_uri_to_string (uri);
+
+ g_assert_cmpstr (uri_str, ==, valid_tests[i].as_string);
+ g_assert_true (soup_uri_is_valid (uri) == valid_tests[i].valid);
+
+ g_free (uri_str);
+ g_uri_unref (uri);
+ }
}

#define CONTENT_TYPE_DEFAULT "text/plain;charset=US-ASCII"
@@ -194,6 +238,8 @@ main (int argc, char **argv)
g_test_add_func ("/uri/copy", do_copy_tests);
g_test_add_func ("/data", do_data_uri_tests);
g_test_add_func ("/path_and_query", do_path_and_query_tests);
+ g_test_add_func ("/uri/valid", do_valid_tests);
+

ret = g_test_run ();

--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/libsoup/libsoup.spec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Summary: libsoup HTTP client/server library
Name: libsoup
Version: %{BaseVersion}.4
Release: 10%{?dist}
Release: 11%{?dist}
License: GPLv2
Vendor: Microsoft Corporation
Distribution: Mariner
Expand Down Expand Up @@ -36,6 +36,7 @@ Patch17: CVE-2025-4476.patch
Patch18: CVE-2025-4948.patch
Patch19: CVE-2025-4969.patch
Patch20: CVE-2025-11021.patch
Patch21: CVE-2026-1467.patch


BuildRequires: meson
Expand Down Expand Up @@ -148,6 +149,9 @@ find %{buildroot} -type f -name "*.la" -delete -print
%defattr(-,root,root)

%changelog
* Wed Feb 04 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.0.4-11
- Patch for CVE-2026-1467

* Wed Oct 29 2025 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.0.4-10
- Patch for CVE-2025-11021

Expand Down
Loading