Bug 2465152 (CVE-2026-10028)

Summary: CVE-2026-10028 glib-networking: Infinite loop in glib-networking GnuTLS backend allows remote denial of service via circular certificate chain
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: unspecifiedCC: gtanzill, jbuscemi, rhel-process-autobot, security-response-team, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in glib-networking. A remote attacker can exploit this vulnerability by presenting a specially crafted certificate chain to an application that uses glib-networking with the GnuTLS backend enabled and performs certificate verification. This crafted chain, which contains circular issuer relationships, can cause an infinite loop during certificate verification. The unbounded traversal consumes excessive CPU resources, leading to a denial of service for the affected process or worker.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-05-04 14:38:04 UTC
AI_ONLY_REPORT
package: glib-networking-2.80.0-3.el10
------
Summary: Denial of Service via Infinite Loop in Circular Certificate Chain  
Traversal: a remote peer can supply a certificate chain whose issuer  
relationships form a cycle, causing unbounded traversal during certificate  
verification in the GnuTLS backend and resulting in a CPU-consuming  
handshake hang.
Requirements to exploit: The attacker must be able to present a crafted  
certificate chain to an application using `glib-networking-2.80.0-3.el10`  
with the GnuTLS backend enabled and certificate verification exercised.  
This is most direct when a server verifies client certificates, or when a  
client connects to an attacker-controlled TLS server.
Component affected: `glib-networking-2.80.0-3.el10`, GnuTLS backend;  
`tls/gnutls/gtlscertificate-gnutls.c` issuer-link construction and  
`tls/gnutls/gtlsdatabase-gnutls.c` `convert_certificate_chain_to_gnutls()`
Version affected: `glib-networking-2.80.0-3.el10`
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH)
AV:N - The vulnerable path is reached during a network TLS handshake.
AC:L - An attacker needs only to present a crafted certificate chain  
that causes cyclic issuer traversal.
PR:N - No prior authentication is required to supply the peer  
certificate chain.
UI:N - In server-side certificate verification scenarios, no separate  
user action is required beyond the network connection.
S:U - The impact is confined to the vulnerable process performing  
certificate verification.
C:N - No confidentiality impact is established by the available evidence.
I:N - No integrity impact is established by the available evidence.
A:H - The affected handshake path can loop indefinitely and consume CPU,  
denying service to the affected process or worker.
Impact: Important. Red Hat classifies flaws that allow remote users to  
cause a denial of service as Important when they can compromise  
availability with relative ease. Here, a remote peer can trigger an  
infinite loop during certificate verification and tie up CPU in the  
handshake path. The issue does not show confidentiality, integrity, or code  
execution impact, and reachability depends on use of the GnuTLS backend and  
the relevant verification path, so Critical is not warranted.
Embargo: no
Reason: The currently established impact is denial of service only,  
with no demonstrated code execution or data exposure. Reachability is also  
dependent on backend and deployment choices, so prompt remediation without  
embargo appears proportionate.
Acknowledgement: Aisle Research
Vulnerability Details: In the GnuTLS backend, peer certificates are  
converted into `GTlsCertificateGnutls` objects and linked through issuer  
checks. The available code allows one peer-provided certificate to be set  
as the issuer of another when `gnutls_x509_crt_check_issuer()` succeeds:
```c
if (j != i &&
gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[j]))
issuer = glib_certs->pdata[j];
if (issuer)
g_tls_certificate_gnutls_set_issuer (glib_certs->pdata[i], issuer);
```
If two certificates in the presented chain mutually satisfy that issuer  
check, the resulting in-memory chain can become cyclic rather than  
terminating at a `NULL` issuer. Later, verification code converts the chain  
for GnuTLS consumption by walking issuer links until `NULL`, but that  
traversal has no cycle detection and no explicit depth bound:
```c
for (cert = G_TLS_CERTIFICATE (chain); cert; cert =  
g_tls_certificate_get_issuer (cert))
gnutls_chain->length++;
for (cert = G_TLS_CERTIFICATE (chain); cert; cert =  
g_tls_certificate_get_issuer (cert), i++)
gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert  
(G_TLS_CERTIFICATE_GNUTLS (cert));
```
The relevant call path is direct: peer certificate retrieval builds the  
chain, and certificate verification later calls  
`convert_certificate_chain_to_gnutls()`. When the issuer graph contains a  
cycle, traversal does not terminate, causing the handshake thread or worker  
to spin indefinitely and consume CPU. Based on the available evidence, this  
is an availability issue in the certificate verification path rather than a  
broader compromise.
Steps to reproduce:
1. Use an application built against `glib-networking-2.80.0-3.el10` with  
the GnuTLS backend enabled.
2. Ensure the application performs certificate verification on a  
peer-supplied chain.
3. Present a crafted certificate chain containing two cross-issued  
certificates such that certificate A is accepted as issuer of B and  
certificate B is accepted as issuer of A.
4. Trigger the TLS handshake so the peer certificate chain is built and  
then verified.
5. Observe that control remains in the issuer-traversal loops inside  
`convert_certificate_chain_to_gnutls()`, with the handshake stalling and  
CPU usage remaining elevated.
Mitigation: Until a fix is available, avoid exposing the affected  
GnuTLS-backed verification path to untrusted peer certificate chains where  
possible. In practice, this means avoiding client-certificate verification  
from untrusted remote parties unless necessary, preferring an alternative  
TLS backend if one is available in the deployment, and enforcing handshake  
or worker timeouts so a stuck verification path cannot tie up service  
resources indefinitely.
Proposed Fix: Add cycle detection and a reasonable depth bound while  
converting the certificate chain, and fail verification cleanly if a  
malformed cyclic chain is detected.
```diff
diff --git a/tls/gnutls/gtlsdatabase-gnutls.c  
b/tls/gnutls/gtlsdatabase-gnutls.c
@@
static CertificateChain *
convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain)
{
GTlsCertificate *cert;
CertificateChain *gnutls_chain;
+  GHashTable *seen;
+  const guint max_depth = 100;
guint i = 0;
gnutls_chain = certificate_chain_new ();
+  seen = g_hash_table_new (g_direct_hash, g_direct_equal);
for (cert = G_TLS_CERTIFICATE (chain); cert; cert =  
g_tls_certificate_get_issuer (cert))
   gnutls_chain->length++;
+    {
+      if (gnutls_chain->length >= max_depth || g_hash_table_contains  
(seen, cert))
+        goto fail;
+      g_hash_table_add (seen, cert);
+      gnutls_chain->length++;
+    }


gnutls_chain->chain = g_new (gnutls_x509_crt_t, gnutls_chain->length);
+  g_hash_table_remove_all (seen);
for (cert = G_TLS_CERTIFICATE (chain); cert; cert =  
g_tls_certificate_get_issuer (cert), i++)
   gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert  
(G_TLS_CERTIFICATE_GNUTLS (cert));
+    {
+      if (i >= gnutls_chain->length || g_hash_table_contains (seen, cert))
+        goto fail;
+      g_hash_table_add (seen, cert);
+      gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert  
(G_TLS_CERTIFICATE_GNUTLS (cert));
+    }


g_assert (i == gnutls_chain->length);
+  g_hash_table_unref (seen);
return gnutls_chain;
+
+fail:
+  g_hash_table_unref (seen);
+  certificate_chain_free (gnutls_chain);
+  return NULL;
}
@@
g_mutex_lock (&priv->mutex);
gnutls_chain = convert_certificate_chain_to_gnutls  
(G_TLS_CERTIFICATE_GNUTLS (chain));
+  if (!gnutls_chain)
+    {
+      g_mutex_unlock (&priv->mutex);
+      return G_TLS_CERTIFICATE_GENERIC_ERROR;
+    }
gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list,
gnutls_chain->chain,  
gnutls_chain->length,
0, &gnutls_result, NULL);
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use