From d41a814759a9fb49584ca8ab3f7295de49a85aa0 Mon Sep 17 00:00:00 2001
From: Alex Gaynor <alex.gaynor@gmail.com>
Date: Mon, 17 Feb 2026 02:04:37 +0000
Subject: [PATCH] Handle exceptions in set_tlsext_servername_callback callbacks

When the servername callback raises an exception, call sys.excepthook
with the exception info and return SSL_TLSEXT_ERR_ALERT_FATAL to abort
the handshake. Previously, exceptions would propagate uncaught through
the CFFI callback boundary, and the handshake would proceed as if the
callback had succeeded, potentially bypassing security-sensitive behavior.

Closes GHSA-vp96-hxj8-p424

Conflict: line numbers adjusted for pyopenssl-20.0.1:
  src/OpenSSL/SSL.py: import sys at line 3; wrapper() at line 1331 (vs 1752 in upstream)
Reference: https://github.com/pyca/pyopenssl/commit/d41a814759a9fb49584ca8ab3f7295de49a85aa0
---
 src/OpenSSL/SSL.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

--- a/src/OpenSSL/SSL.py	2020-11-05 00:00:00.000000000 +0800
+++ b/src/OpenSSL/SSL.py	2026-03-18 00:00:00.000000000 +0800
@@ -1,5 +1,6 @@
 import os
 import socket
+import sys
 from sys import platform
 from functools import wraps, partial
 from itertools import count, chain
@@ -1331,7 +1332,11 @@
 
         @wraps(callback)
         def wrapper(ssl, alert, arg):
-            callback(Connection._reverse_mapping[ssl])
+            try:
+                callback(Connection._reverse_mapping[ssl])
+            except Exception:
+                sys.excepthook(*sys.exc_info())
+                return _lib.SSL_TLSEXT_ERR_ALERT_FATAL
             return 0
 
         self._tlsext_servername_callback = _ffi.callback(