Skip to content

feat(python-worker): add sandboxed HTTP proxy transport - #5

Merged
sundy-li merged 2 commits into
mainfrom
feat/python-worker-egress-proxy
Oct 31, 2026
Merged

sundy-li merged 2 commits into
mainfrom
feat/python-worker-egress-proxy

Conversation

@sundy-li

Copy link
Copy Markdown

Summary

  • Follow up on feat(python-worker): add host-controlled outbound network policy #4 with a distinct Linux-only HTTP(S) proxy transport, WorkerCommand::network_proxy. Keep allow_network = false; configuring direct networking together with a proxy fails rather than falling back to unrestricted networking. Existing default-deny and compatibility modes remain unchanged.
  • Connect a private Unix control channel before confinement. Proxy-aware Python clients use local stream endpoints transferred through that channel to a trusted host NetworkProxy; native Internet socket creation remains denied by seccomp. Python adaptation supplies compatibility, not authorization. No public TCP proxy listener or worker-side DNS/network permission is needed.
  • Keep target authorization, DNS and HTTP proxy execution in the host: implementations must validate every HTTP target and HTTPS CONNECT destination with trusted policy context and enforce limits/revocation. This PR provides transport only, not Databend SQL integration binding or its allowlist implementation. It prepares the dependency layer for reusing Databend's existing NETWORK RULE / EXTERNAL ACCESS INTEGRATION model from feat(query): manage remote UDF access with SQL integrations databendlabs/databend#20787; the broader compatibility flag is tracked in feat(query): add admin Python UDF network exception databendlabs/databend#20874.
  • Bound active host proxy tasks to 32 per worker, validate transferred descriptors and close them on malformed messages, use CLOEXEC, and cancel proxy tasks when the worker handle is dropped. Preserve filesystem/process confinement; allow public trust-store reads for client TLS verification. macOS refuses this mode rather than claiming a sandbox it cannot enforce.
  • Scope: synchronous proxy-aware HTTP(S), including urllib and requests. No arbitrary TCP/UDP or async/native-socket client support. CONNECT contents remain end-to-end encrypted; host implementations must define and enforce revocation for existing tunnels. This transport alone does not promise instantaneous revocation or authorize any destination.
  • Validation passed on Linux x86_64 with Python 3.12: cargo test -p arrow-udf-python-worker (8 unit tests plus existing and new real-worker suites), cargo clippy -p arrow-udf-python-worker --all-targets -- -D warnings, cargo fmt --all --check, and diff checks. New coverage includes native/direct socket denial, missing-policy defaults, malformed/truncated/multiple/wrong-type descriptors, CLOEXEC, local HTTP, verified HTTPS, denied redirects/CONNECT, policy changes on an existing worker, concurrent requests and cancellation cleanup.
  • Also passed ARROW_UDF_TEST_REQUESTS=1 cargo test -p arrow-udf-python-worker --test network_proxy with requests 2.32.5 installed in an isolated PYTHONPATH: HTTP, verified HTTPS, redirect denial and no direct fallback with trust_env = false. Tests do not fetch from external destinations; optional client packages are installed separately. macOS/aarch64 builds and full-workspace tests were not run locally.

AI assistance

  • AI usage: An AI coding agent drafted the proxy transport, Python client adapter, regression tests, documentation and PR description, and ran local validation; the responsible human reviewed the full final diff before submission.
  • Responsible human: @sundy-li
  • The responsible human has read every line of this diff and can explain each change

On MSG_CTRUNC, macOS can keep the untruncated cmsg_len. receive_stream
trusted it, adopted bytes past the written control buffer as OwnedFds
and closed unrelated descriptors, aborting the macOS lib tests with an
IO safety violation. Bound each SCM_RIGHTS header by msg_controllen,
stop on malformed short headers, and add a platform-independent test.
@sundy-li
sundy-li marked this pull request as ready for review October 31, 2026 02:00
@sundy-li
sundy-li merged commit 6a49de9 into main Oct 31, 2026
8 checks passed
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.

1 participant