Skip to content

Fix strict_cert proxy bypass and loopback SO_REUSEADDR on Windows - #336

Open
Flerpharos wants to merge 1 commit into
mainfrom
fix/327-proxy-tls-and-reuseaddr
Open

Fix strict_cert proxy bypass and loopback SO_REUSEADDR on Windows#336
Flerpharos wants to merge 1 commit into
mainfrom
fix/327-proxy-tls-and-reuseaddr

Conversation

@Flerpharos

Copy link
Copy Markdown
Collaborator

Fixes #327

Two low-severity networking fixes in src/labapi/client.py:

  1. Proxy TLS bypass: _313HTTPAdapter only overrode init_poolmanager, so the relaxed SSL context (strict_cert=False, which drops VERIFY_X509_STRICT) was never applied to requests routed through an HTTPS proxy — proxy_manager_for built its pool manager with default strict verification, silently ignoring the setting. Fixed by storing the built ssl_context on the adapter and overriding proxy_manager_for to pass the same context through to the parent implementation.

  2. Loopback callback SO_REUSEADDR on Windows: the auth callback TCPServer unconditionally set allow_reuse_address = True. On POSIX this is the benign TIME_WAIT-reuse behavior. On Windows, SO_REUSEADDR instead permits another local process to bind the same 127.0.0.1:<port> while the listener is up, letting it race for the auth_code/email callback. Fixed with a platform conditional: on Windows, allow_reuse_address stays False and a server_bind override sets SO_EXCLUSIVEADDRUSE instead; POSIX behavior is unchanged.

Testing

  • Added test_strict_cert_false_relaxes_ssl_for_direct_and_proxied_requests, which asserts the adapter stores ssl_context and that proxy_manager_for injects the same context into its pool manager.
  • Added test_collect_auth_response_blocks_concurrent_bind_on_windows (skipped off Windows), which binds the loopback listener via client.collect_auth_response() and asserts a second socket (even with SO_REUSEADDR set) cannot bind the same port. Verified this reproduces the pre-fix vulnerability directly at the socket level (two SO_REUSEADDR sockets can share a port on Windows) and that the fix blocks it (PermissionError/WinError 10013).
  • Ran the full suite (uv run pytest --ignore=tests/test_integration.py) five times in a row on Windows to check for rebind flakiness from disabling SO_REUSEADDR: consistently 432 passed, 1 skipped, no flakes.
  • uv run ruff check . and uv run ruff format --check . pass; pre-commit's pyright hook passes on the changed files.

🤖 Generated with Claude Code

… on Windows

_313HTTPAdapter only overrode init_poolmanager, so strict_cert=False had no
effect for requests routed through an HTTPS proxy (proxy_manager_for built a
pool manager with default strict SSL verification). Store the relaxed
ssl_context on the adapter and reuse it in proxy_manager_for too.

The loopback auth callback server unconditionally set
allow_reuse_address = True. On POSIX this is benign (TIME_WAIT reuse), but on
Windows SO_REUSEADDR lets an unrelated process bind the same port while the
listener is up, letting it race for the auth_code/email callback. On Windows,
disable allow_reuse_address and set SO_EXCLUSIVEADDRUSE instead; POSIX
behavior is unchanged.

Fixes #327
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

strict_cert=False ignored behind an HTTPS proxy; loopback callback uses SO_REUSEADDR

1 participant