Skip to content

Commit d457221

Browse files
Add certifi fallback for SSL certificate issues
Using Claude 4 Sonnet
1 parent 7e3ab80 commit d457221

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

requirements/optional.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ SQLAlchemy>=1.4,<3
1414
# websockets 9 is not compatible with Python 3.10
1515
websockets>=9.1,<16
1616
websocket-client>=1,<2
17+
# SSL certificate bundle for certificate verification issues
18+
certifi

slack_sdk/web/async_base_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
_get_url,
1919
get_user_agent,
2020
)
21+
from .ssl_utils import create_ssl_context_with_certifi_fallback
2122
from ..proxy_env_variable_loader import load_http_proxy_from_env
2223

2324
from slack_sdk.http_retry.builtin_async_handlers import async_default_handlers
@@ -55,7 +56,7 @@ def __init__(
5556
"""The maximum number of seconds the client will wait
5657
to connect and receive a response from Slack.
5758
Default is 30 seconds."""
58-
self.ssl = ssl
59+
self.ssl = create_ssl_context_with_certifi_fallback(ssl)
5960
"""An [`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html#ssl.SSLContext)
6061
instance, helpful for specifying your own custom
6162
certificate chain."""

slack_sdk/web/base_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
_build_unexpected_body_error_message,
3030
_upload_file_via_v2_url,
3131
)
32+
from .ssl_utils import create_ssl_context_with_certifi_fallback
3233
from .slack_response import SlackResponse
3334
from slack_sdk.http_retry import default_retry_handlers
3435
from slack_sdk.http_retry.handler import RetryHandler
@@ -67,7 +68,7 @@ def __init__(
6768
"""The maximum number of seconds the client will wait
6869
to connect and receive a response from Slack.
6970
Default is 30 seconds."""
70-
self.ssl = ssl
71+
self.ssl = create_ssl_context_with_certifi_fallback(ssl)
7172
"""An [`ssl.SSLContext`](https://docs.python.org/3/library/ssl.html#ssl.SSLContext)
7273
instance, helpful for specifying your own custom
7374
certificate chain."""

slack_sdk/web/ssl_utils.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import os
2+
import ssl
3+
from ssl import SSLContext
4+
from typing import Optional
5+
6+
7+
def has_ssl_env_vars() -> bool:
8+
"""Check if SSL-related environment variables are set"""
9+
ssl_env_vars = ["SSL_CERT_FILE", "SSL_CERT_DIR", "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE"]
10+
return any(os.environ.get(var) for var in ssl_env_vars)
11+
12+
13+
def create_ssl_context_with_certifi_fallback(custom_ssl: Optional[SSLContext] = None) -> Optional[SSLContext]:
14+
"""Create SSL context with certifi fallback for certificate issues
15+
16+
Priority:
17+
1. If custom_ssl is provided or SSL env vars are set -> return custom_ssl
18+
2. If certifi is available -> use certifi's certificate bundle
19+
3. Otherwise -> return custom_ssl (usually None)
20+
21+
This helps resolve SSL certificate issues on Windows by using certifi's
22+
curated certificate bundle when no explicit SSL configuration is provided.
23+
"""
24+
# Use custom_ssl if provided, or respect SSL environment variables
25+
if custom_ssl is not None or has_ssl_env_vars():
26+
return custom_ssl
27+
28+
# Fall back to certifi if available (helps with Windows SSL issues)
29+
try:
30+
import certifi
31+
32+
return ssl.create_default_context(cafile=certifi.where())
33+
except ImportError:
34+
return custom_ssl

0 commit comments

Comments
 (0)