Skip to content

fix(deps): bundle socksio so httpx Client doesn't crash inside fence sandbox#96

Merged
sohil-kshirsagar merged 2 commits intomainfrom
sohil/fix/bundle-socksio-for-replay-sandbox
May 8, 2026
Merged

fix(deps): bundle socksio so httpx Client doesn't crash inside fence sandbox#96
sohil-kshirsagar merged 2 commits intomainfrom
sohil/fix/bundle-socksio-for-replay-sandbox

Conversation

@sohil-kshirsagar
Copy link
Copy Markdown
Contributor

@sohil-kshirsagar sohil-kshirsagar commented May 8, 2026

Adds socksio as a hard dep of tusk-drift-python-sdk so that any Python service constructing httpx.Client(...) at module load time doesn't crash during Tusk Drift replay with ImportError: Using SOCKS proxy, but the 'socksio' package is not installed.

Why

The replay sandbox is built on fence, which runs local SOCKS5 + HTTP proxies and injects these into the sandboxed service's environment so well-behaved HTTP libraries route through it:

ALL_PROXY=socks5h://localhost:1080
HTTP_PROXY=http://localhost:3128
HTTPS_PROXY=http://localhost:3128

httpx evaluates proxy config eagerly inside Client.__init__ — the moment it sees ALL_PROXY=socks5h://..., it tries to import socksio to construct a SOCKS5 transport. If socksio isn't installed, it raises ImportError at construction. So a perfectly normal Python pattern like:

import httpx

_client = httpx.Client(base_url=settings.INTERNAL_BASE_URL, ...)

…blows up at import time during replay (but not in prod, staging, or local dev, because none of those have ALL_PROXY=socks5h://... set). The traceback ends with:

ImportError: Using SOCKS proxy, but the 'socksio' package is not installed.
Make sure to install httpx using `pip install httpx[socks]`.

The WSGI/Flask/Django app never finishes loading, the drift CLI's readiness check fails, and the run errors out with service failed to become ready within 3m0s. From the customer's POV this looks like a bug in their code or our SDK — but the actual cause is an environmental side-effect of fence's proxy mechanism.

Why bundling here

Three options were considered:

Option Where it lives Trade-off
httpx.Client(..., trust_env=False) per Client Customer code Targeted, but per-Client and won't generalize
Add socksio to customer deps Customer code Project-wide, but customer needs to know about the issue first
Bundle socksio in the SDK This PR Auto-applies to every Python customer; +100KB unused for customers who don't use httpx + fence together

Bundling is the lowest-friction long-term fix. socksio is ~100KB, pure Python, MIT-licensed, with zero transitive deps — essentially free to ship. It eliminates the failure mode without any customer involvement.

What socksio does at runtime

Effectively nothing visible:

  1. Replay (the only place fence engages): httpx.Client(...) reads ALL_PROXY=socks5h://..., imports socksio successfully, builds a SOCKS5 transport, attaches it to the Client's _mounts. The Client constructor returns normally; Flask/WSGI starts. When app code calls client.get(...), the SDK's monkey-patch on httpx.Client.send intercepts above the transport layer and returns a recorded mock — the SOCKS transport never actually serves a request.
  2. Recording: fence isn't engaged, no proxy env vars set, socksio is dormant.
  3. Customer prod / staging / local dev: same as recording.

The only behavior change is "Client constructor doesn't crash when the env happens to have a SOCKS proxy URL set."

Why only socksio and not also PySocks / aiohttp-socks

Considered bundling broader SOCKS support for requests / urllib3 / aiohttp, but:

  • httpx is unique in that it eagerly evaluates proxy config inside Client.__init__. The SOCKS-related import fires at construction, before any monkey-patch can intercept.
  • requests, urllib3, and aiohttp all evaluate proxy config lazily on .send() / .request(). The SDK's monkey-patches on Session.send / PoolManager.urlopen / ClientSession.send sit above proxy resolution, so a missing PySocks / aiohttp-socks would only matter for un-intercepted traffic — which generally indicates a bigger problem (replay isn't being mocked) and isn't worth a default dep.

Will document a per-case workaround (pip install requests[socks], etc.) if a request-time SOCKS failure ever shows up.

Risk / blast radius

  • Pip install size: +~100KB.
  • Lockfile churn: customers using uv / poetry / pip-tools see a new transitive package on next lock. socksio is stable on 1.x since 2020, pure Python, no transitive deps.
  • Runtime behavior: only changes if ALL_PROXY / HTTPS_PROXY / HTTP_PROXY is set with a SOCKS scheme AND the process constructs an httpx Client. In every other case socksio is unused.
  • License: socksio is MIT, compatible with the SDK's Apache-2.0 license.
  • Python version support: socksio supports Python 3.6+, no compatibility floor change.

httpx evaluates proxy config eagerly inside Client.__init__ — when fence
injects ALL_PROXY=socks5h://localhost:1080 and the customer's app constructs
an httpx.Client at module load time, httpx tries to import socksio to build
a SOCKS5 transport. Without socksio installed, the import raises and the
WSGI/Flask app fails to start before serving a single request.

Bundling socksio as a hard dep (~100KB, pure Python, MIT, zero transitive
deps) covers every Python customer using httpx without any code or config
change on their end. The SOCKS transport gets constructed but never serves
a request — the SDK's monkey-patches on Client.send sit above the transport
layer, so during replay the proxy is dormant.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5ead518. Configure here.

Comment thread pyproject.toml Outdated
@sohil-kshirsagar sohil-kshirsagar marked this pull request as ready for review May 8, 2026 00:31
@tusk-dev
Copy link
Copy Markdown
Contributor

tusk-dev Bot commented May 8, 2026

Tip

New to Tusk? Learn more here.

Code Review

Tusk Review: No issues found


Unit Tests

PR identified as a dependency upgrade

View output

Last run on 0b50cf7. Comment @use-tusk generate to create a test suite on the latest commit. Configure here.

View check history

Commit Unit Tests Created (UTC)
5ead518 PR identified as a dependency upgrade · Output May 8, 2026 12:31AM
0b50cf7 PR identified as a dependency upgrade · Output May 8, 2026 12:42AM

@sohil-kshirsagar sohil-kshirsagar requested a review from jy-tan May 8, 2026 00:41
@sohil-kshirsagar sohil-kshirsagar merged commit d2e3e27 into main May 8, 2026
9 checks passed
@sohil-kshirsagar sohil-kshirsagar deleted the sohil/fix/bundle-socksio-for-replay-sandbox branch May 8, 2026 05:25
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.

2 participants