Skip to content

feat(v1): DockerConfig.network_access to block the workload's internet#2014

Open
eligotts wants to merge 1 commit into
mainfrom
feat/docker-block-internet
Open

feat(v1): DockerConfig.network_access to block the workload's internet#2014
eligotts wants to merge 1 commit into
mainfrom
feat/docker-block-internet

Conversation

@eligotts

@eligotts eligotts commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds network_access: bool = True to DockerConfig — mirroring PrimeConfig/ModalConfig, so --harness.runtime.network-access false now works uniformly across all three runtimes (docker was the only one missing it).

When false, the container's DNS resolver is disabled, so every hostname-based fetch (pip install, git clone, curl <host>) fails — while the interception model tunnel keeps working, because it egresses from the host, not the container: the container only reaches host.docker.internal / host loopback, which needs no DNS.

The motivating use case is local-docker eval of tasks on public seed repos, where the agent must not be able to fetch upstream source / packages (a leakage / cheating vector) but must still reach the model.

How

Platform-specific, matching the existing host_url() split:

  • Docker Desktop (macOS/Windows): drop --network host for the default bridge, add --dns 0.0.0.0 and --add-host=host.docker.internal:host-gateway (the host route is pinned in /etc/hosts, so it resolves without DNS; host_url() already points the tunnel there on non-Linux).
  • Linux: keep --network host (interception is reachable at 127.0.0.1) and add --dns 0.0.0.0. --dns writes a container-private resolv.conf (Docker marks it "Overrides: [nameservers]"), so the host's own DNS is untouched.

Default stays True, so existing behavior is unchanged.

Scope / caveat

This is a DNS-level block, not an IP-level airgap — a hardcoded raw IP could still egress. It's aimed at the real leak vectors (all hostname-based: pip / git / curl-by-host). For a hard airgap, an iptables egress allowlist would be needed; that's deliberately out of scope here.

--network none / --internal networks were rejected during design: on Docker Desktop they sever the host route along with the internet, killing the tunnel too (verified).

Test plan

  • Linux path (simulated via two --network host containers sharing the Docker VM netns — same daemon/netns code as a real Linux host): daemon accepts --network host --dns 0.0.0.0; host-loopback service reachable (200); pypi unreachable; container-private resolv.conf confirmed.
  • macOS path (native): host tunnel reachable (200) via host.docker.internal; pip install / git clone to public hosts fail.
  • End-to-end: a local-docker eval with --harness.runtime.type docker --harness.runtime.network-access false solves a task (reward 1.0, 59 model calls over the tunnel, no errors) while pip/git to public hosts fail from inside the container.

Note for reviewers: offline harness bootstrap

A blocked run needs an image whose harness can bootstrap offline. Currently _ENSURE_UV (runtimes/base.py) runs pip install -U uv unconditionally at harness setup — which needs the network even when uv is already present in the image (its curl fallback needs network too). So a network_access=false run only boots on an image with a pre-warmed uv cache. Making _ENSURE_UV short-circuit when uv is already on PATH would let any uv-bearing image boot offline; happy to send that as a small follow-up if you'd like it.

🤖 Generated with Claude Code

Note

Add network_access field to DockerConfig to block internet access in workloads

  • Adds a network_access boolean field (default True) to DockerConfig in docker.py; setting it to False disables DNS to block internet access.
  • Extracts a _network_args() helper that generates the appropriate docker run networking flags based on network_access and the host platform.
  • On Linux, network_access=False uses --network host --dns 0.0.0.0; on non-Linux, it omits host networking and uses --dns 0.0.0.0 --add-host host.docker.internal:host-gateway.
  • Startup logs now append , internet blocked when network_access=False.

Macroscope summarized 9b11fbf.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 400c94e. Configure here.

Comment thread verifiers/v1/runtimes/docker.py Outdated
interception model tunnel keeps working, because it egresses from the HOST, not the
container: the container only reaches `host.docker.internal` / host loopback, which needs
no DNS. This is a DNS-level block, not an IP-level airgap (a hardcoded raw IP could still
egress). Mirrors prime/modal's `network_access`, except those sever the tunnel too."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing evaluate skills reference update

Low Severity

DockerConfig now exposes network_access, but skills/evaluate-environments/references/REFERENCE.md still describes Docker as always using host networking and does not document the new field, unlike PrimeConfig and ModalConfig.

Fix in Cursor Fix in Web

Triggered by project rule: BugBot Instructions

Reviewed by Cursor Bugbot for commit 400c94e. Configure here.

@macroscopeapp

macroscopeapp Bot commented Jul 15, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

New feature introducing network isolation capability for Docker workloads. Changes container networking behavior with platform-specific logic (Linux vs Docker Desktop). New capabilities warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Adds `network_access: bool = True` to DockerConfig (mirroring prime/modal, so
`--harness.runtime.network-access false` now works uniformly across all three
runtimes). When false, the container's DNS resolver is disabled so every
hostname-based fetch (pip install, git clone, curl <host>) fails — while the
interception model tunnel keeps working, because it egresses from the HOST, not
the container: the container only reaches host.docker.internal / host loopback,
which needs no DNS.

Platform-specific (matching the existing host_url() split):
- Docker Desktop (macOS/Windows): drop --network host for the bridge, add
  --dns 0.0.0.0 and --add-host=host.docker.internal:host-gateway (host route
  pinned in /etc/hosts, resolves without DNS).
- Linux: keep --network host (interception is reachable at 127.0.0.1) and add
  --dns 0.0.0.0. --dns writes a container-private resolv.conf, so the host's own
  DNS is untouched.

A DNS-level block, not an IP-level airgap: a hardcoded raw IP could still egress;
use an iptables egress allowlist if that matters.

Verified end-to-end: a local-docker eval with --harness.runtime.network-access
false solves a task (reward 1.0, 59 model calls over the tunnel) while pip/git to
public hosts fail from inside the container.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@eligotts
eligotts force-pushed the feat/docker-block-internet branch from 400c94e to 9b11fbf Compare July 15, 2026 01:01
"" if self.config.network_access else ", internet blocked",
)

def _network_args(self) -> list[str]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i dont like util function as methods. can we inline this logic in start()

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