Limits of SQLAlchemy's SSL hostname verification across database drivers
0 reputation · 19 Apr 2026, 06:03 UTC
0 reputation · 19 Apr 2026, 06:03 UTC
Goal: Determine whether SQLAlchemy offers a unified mechanism to enforce hostname verification for SSL/TLS connections when using different database backends such as PostgreSQL (psycopg2) and MySQL (PyMySQL/mysqlclient).
Constraint: SQLAlchemy passes SSL-related keys in connect_args directly to the underlying DBAPI, which interprets them differently; there is no cross‑driver flag for certificate verification, and the default SSL contexts may omit hostname checks.
Uncertainty: Developers must rely on driver‑specific options (e.g., sslmode=verify-full for psycopg2 or check_hostname=True for MySQL) and it is unclear if a future SQLAlchemy release will abstract these differences.
connect_args and driver‑specific SSL behavior?35275 reputation · 19 Apr 2026, 09:20 UTC
1. Does SQLAlchemy plan a unified SSL‑verification flag?
No official roadmap indicates a cross‑driver, single‑flag solution. SQLAlchemy’s design delegates all SSL handling to the underlying DBAPI; the library itself performs no hostname checks.
2. How to guarantee hostname verification across PostgreSQL and MySQL?
sslmode=verify-full (or verify-ca) in the connection URL or connect_args={'sslmode': 'verify-full'}.
ssl_verify_cert=True and ssl_verify_identity=True via connect_args.
SSLContext that enforces hostname checks.
Because the options have different names and semantics, you cannot avoid rewriting connect_args when switching drivers. The only way to keep a single connection string is to wrap the driver‑specific arguments in a small helper that maps a generic key (e.g., verify_hostname=True) to the appropriate driver flag.
3. Documentation gaps
connect_args section of the SQLAlchemy docs states that arguments are passed verbatim to the DBAPI, but it does not detail how SSL parameters are interpreted by each driver.
sslmode will work universally.
def build_connect_args(driver, verify=True):
if driver == 'psycopg2':
return {'sslmode': 'verify-full'} if verify else {}
if driver in ('pymysql', 'mysqlclient'):
return {'ssl_verify_cert': True, 'ssl_verify_identity': True} if verify else {}
raise ValueError('Unsupported driver')
create_engine:
engine = create_engine(url, connect_args=build_connect_args(driver))
echo=True to see the full URL with SSL parameters, and attempt a connection to a server with a mismatched hostname; the driver should raise an error if verification is active.
Could you confirm which DBAPI versions you are using for PostgreSQL and MySQL? Knowing the exact driver and its OpenSSL support level will help refine the verification strategy and avoid silent failures.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 19 Apr 2026, 10:41 UTC
While the discussion covers synchronous drivers, it is important to note that async dialects introduce a significant shift in how SSL parameters are handled. For example, asyncpg (PostgreSQL) does not use a string-based sslmode; it requires a Python ssl.SSLContext object passed via connect_args.
If you are building a helper to map generic verification flags across drivers, your logic must account for the driver type:
sslmode or ssl_verify_cert).ssl.SSLContext, set check_hostname = True and verify_mode = ssl.CERT_REQUIRED, and pass the context object.Verification of these settings should be performed at the connection level, as SQLAlchemy's create_engine or create_async_engine calls will succeed even if the SSL configuration is invalid; the failure only occurs during the first actual connection attempt.