Skip to content

fix: honour verify=False/ssl=False in HttpOptions client_args#2558

Open
64johnlee wants to merge 1 commit into
googleapis:mainfrom
64johnlee:fix/ssl-verify-false-truthiness
Open

fix: honour verify=False/ssl=False in HttpOptions client_args#2558
64johnlee wants to merge 1 commit into
googleapis:mainfrom
64johnlee:fix/ssl-verify-false-truthiness

Conversation

@64johnlee
Copy link
Copy Markdown

Summary

Fixes #2557

When a user passes verify=False (httpx) or ssl=False (aiohttp/websocket) in HttpOptions.client_args to disable SSL certificate verification — a common need in air-gapped, corporate proxy, or local-dev environments — the SDK silently ignored it and replaced it with a default strict ssl.SSLContext.

Root cause

Three static helper methods (_ensure_httpx_ssl_ctx, _ensure_aiohttp_ssl_ctx, _ensure_websocket_ssl_ctx) used truthiness guards:

ctx = args.get('verify')   # user passed False → ctx = False
if not ctx:                # not False == True → enters branch
    ctx = ssl.create_default_context(...)  # overwrites False!

And inside _maybe_set:

if not args or not args.get(verify):   # not False == True → overwrites again
    args[verify] = ctx

Fix

Replace if not ctx:if ctx is None: and not args.get(verify)args.get(verify) is None in all three helpers (6 changes total). This correctly distinguishes "user explicitly set False" from "user provided nothing".

Input Before After
verify=False replaced with ssl.SSLContext preserved as False
verify=ssl.SSLContext(...) preserved ✅ preserved ✅
verify absent default ssl.SSLContext injected ✅ default ssl.SSLContext injected ✅

Tests

Added 5 unit tests to test_http_options.py covering all three helpers with False input and verifying the default-injection path still works. 15/15 pass; no new failures introduced (pre-existing 33 failures unchanged).

🤖 Generated with Claude Code

The three _ensure_*_ssl_ctx helpers guarded the SSL context with
`if not ctx`, which evaluated `False` (the falsy boolean the user
passes to disable SSL verification) as "no context provided" and
silently replaced it with a default strict SSLContext.

Changed all three guards to `if ctx is None` so that only a genuinely
absent value triggers default context creation. The _maybe_set inner
functions received the same treatment: `not args.get(verify)` became
`args.get(verify) is None` so an explicit False is never overwritten.

Affected methods:
- _ensure_httpx_ssl_ctx  (verify key, sync + async client args)
- _ensure_aiohttp_ssl_ctx (ssl key, async client args)
- _ensure_websocket_ssl_ctx (ssl key, async client args)

Fixes googleapis#2557

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@google-cla
Copy link
Copy Markdown

google-cla Bot commented Jun 6, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@Venkaiahbabuneelam Venkaiahbabuneelam self-assigned this Jun 8, 2026
@Venkaiahbabuneelam Venkaiahbabuneelam added the size:L Code changes between 40-100 lines label Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L Code changes between 40-100 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] google-genai Python SDK overrides 'verify=False' in HttpOptions due to truthiness evaluation quirk

2 participants