Skip to content

Block metadata/link-local egress and separate dep-install network from code execution #100

Description

@las7

Summary

When a sandbox container is given network access, it gets Docker's default bridge with no egress controls, and the networked dependency-install phase is not separated from untrusted code execution.

  • --network=bridge is set at container creation and never changed (tako_vm/execution/worker.py:1430-1436; tako_vm/sandbox.py:591-592). There is no --dns, no internal network, no destination allowlist, and no link-local/metadata block anywhere (grep for 169.254/iptables/--add-host/--dns finds nothing).
  • entrypoint.sh runs dep-install (uv pip install) and then the user code in the same container on the same bridge. So whenever a job installs a package, user code has full outbound network for the entire run.
  • gVisor does not help here: runsc sandboxes syscalls, not L3 egress.

Exploitable consequences when the bridge is attached: reach the cloud metadata endpoint (169.254.169.254) for instance IAM credentials, SSRF to host/internal services, and exfiltration of /code and /input.

The server path gates the bridge behind opt-in (allow_runtime_requirements, default false; or job_type.network_enabled, default false), so this is not the zero-config default. But the library Sandbox path has no allow_runtime_requirements gate at all (sandbox.py:591): passing any requirement attaches the bridge. Also note dependency_proxy_url is install-only (it sets HTTP(S)_PROXY for uv, unset before user code runs) and provides no enforcement on user-code sockets.

Proposed changes

  1. Block link-local / metadata ranges (at minimum 169.254.0.0/16) for any sandbox network.
  2. Separate the networked install phase from code execution: install in a distinct step/container/netns, then run user code with --network=none. (If install runs under its own container, it also closes the root-during-install window, see related issue.)
  3. Add the allow_runtime_requirements gate to the library Sandbox path so SDK behavior matches the server.
  4. If outbound is genuinely needed for a job type, make it an explicit allowlist rather than an open bridge.

Pointers

  • tako_vm/execution/worker.py:1430-1436 — network selection
  • tako_vm/sandbox.py:591-594 — library path (ungated)
  • docker/entrypoint.sh — install then exec, same container
  • tako_vm/config.py:409-416allow_runtime_requirements, dependency_proxy_url

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitysecurity related

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions