You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Python Client does not enforce its required TLS connection policy #30061
Checked relevant Python SDK issues; this report concerns the SDK client path.
Environment
Repository main 3e50e1b32d8da61bbbf70c89989fb08b671809de, Python 3.12, SQLAlchemy 1.4/2.x. Initial findings were reproduced offline with synthetic inputs; real-service validation will be linked from the implementation PR.
Priority: P0.
Actual behavior and reproduction
Capture arguments passed by _create_engine() after connect(..., ssl_mode='required', ssl_ca=None). The stored required/certificate/identity flags are not propagated. ssl_mode='disabled' is also not consistently sent to the driver. Driver versions differ in opportunistic TLS/fallback behavior, so storing a mode alone does not enforce it.
Expected behavior
Required mode must verify certificate trust and hostname, use system roots if no CA file is supplied, and refuse peers without TLS before authentication. Disabled mode must disable TLS. Explicit certificate settings must have a defined policy.
Design and acceptance tests
Use an explicit validating SSLContext for required mode and a compatibility guard against pre-authentication plaintext fallback on older supported PyMySQL versions. Verify supplied/system CA handling, hostname mismatch, untrusted certificates, no-TLS peers and driver mode propagation with actual transport tests.
This is distinct from server handshake issue #29928. Public evidence must use locally generated test certificates and synthetic credentials, not real secrets.
Implementation tracking
#30074 — draft implementation with regression cases and recorded local validation. Pending review/merge; the issue closes on merge.
TLS stress also encountered the existing server transport issue #29928; that failed run is explicitly retained in the PR. Dedicated certificate/no-downgrade tests use precise failure assertions.
Activity
Ariznawlll commentedon Oct 20, 2026
测试版本
main,完整 commit21966565287edf9f7d7f519af60d269711608945;服务端git_version()=2196656528。8ef2eaf4d923bdb4136dd81a50850e8eced0f368;GitHub main compare 已确认包含该修复。mo-service(1 CN / 1 TN / 1 LogService,MySQL 127.0.0.1:6001),分别用独立的 TLS-enabled 与明文配置运行;本地生成仅用于验收的短期自签名证书,SAN 为IP:127.0.0.1。Python 3.12 SDK,SQLAlchemy 2.1.5,分别使用 PyMySQL 1.2.3 与 1.0.0。未使用生产证书或凭据。原问题验证
在真实 TLS-enabled MO 协议连接上,对两版 PyMySQL 各连续三轮运行
test_sdk_connection_contracts.py的四个 TLS 用例:ssl_mode='required'+ 指定受信本地 CA:认证和SELECT 1成功,底层 socket 实测为ssl.SSLSocket。localhost(证书仅含 IP SAN):证书主机名校验失败,SDK 未报告已连接。ssl_mode='disabled':底层 socket 确认为非ssl.SSLSocket。以上四项在 PyMySQL 1.2.3 为每项 3/3,在 PyMySQL 1.0.0 也为每项 3/3。随后在同一隔离服务的明文配置下,对两版驱动分别三轮验证
required连接被明确拒绝(不发生明文回退)、disabled连接仍可用;两版各 2 项 × 3/3 通过。旧版 PyMySQL 的回退风险被实际覆盖。Happy Path 覆盖
SELECT 1 = 1,并确认为加密 socket。ssl_ca=None时构造的 SDK SSLContext 实际加载 188 个当前系统根证书,verify_mode=CERT_REQUIRED、check_hostname=True;这是系统信任库配置检查,不声称连接了公网受信证书服务端。Unhappy Path 覆盖
白盒验证
当前 main 的
tls_options使用ssl.create_default_context(cafile=...)建立证书和主机名校验;TLSRequiredConnection._request_authentication在服务端不宣告 TLS 时于认证请求前抛错。离线test_connection_contracts.py与本轮实际协议测试覆盖两者。未运行 Python-race(不适用)。回归测试
CI Required成功;SDK online job 被跳过。本轮补跑上述本地 online TLS 路径;没有运行完整 SDK online suite,也没有公网受信 CA 服务器的正向系统根握手测试。测试证据
git_version()=2196656528;PyMySQL 1.2.3 和 1.0.0 的 TLS-enabled 四项用例各轮均显示4 passed,明文两项各轮均显示2 passed。成功路径断言ssl.SSLSocket,失败路径断言证书错误/非 TLS 拒绝与状态清理。测试结论
测试通过。