Skip to content

fix: make strict sandbox survive docker-compose services#139

Merged
jy-tan merged 2 commits intomainfrom
docker-fix
Apr 24, 2026
Merged

fix: make strict sandbox survive docker-compose services#139
jy-tan merged 2 commits intomainfrom
docker-fix

Conversation

@jy-tan
Copy link
Copy Markdown
Contributor

@jy-tan jy-tan commented Apr 24, 2026

Summary

Three fixes for fence-sandboxed docker compose up (and similar host-daemon-delegated services) on Linux. Each also cleans up a leaky abstraction that caused the underlying bug.

  1. resolv.conf overmount: the cross-mount resolv.conf handler was emitting --tmpfs /run on stock Ubuntu w/ systemd-resolved, wiping /run/docker.sock. The guard that would have prevented this was scoped to defaultDenyRead mode only; it now applies in both modes.
  2. Reverse-bridge collision: new Manager.SetService(ServiceOptions{..., ExecutionModel: ServiceBindsOnHost}) lets callers signal that the sandboxed process delegates port binding to an external daemon (docker, podman, systemctl). Fence skips its reverse socat bridge in that case, avoiding a host-port collision with the daemon's own bind. Replaces SetExposedPorts (breaking change).
  3. Host file invisibility: new Manager.ExposeHostPath(path, writable) API. Emits a --ro-bind / --bind after all tmpfs overmounts so callers can hand over a host-generated file (e.g. an os.CreateTemp("", ...) path under /tmp, which fence tmpfs-overmounts) without reverse-engineering fence's mount plan. On macOS, adds the path to the seatbelt allowlist.

Changes

  • internal/sandbox/manager.go: ServiceOptions, ServiceExecutionModel, SetService, ExposeHostPath; replaces SetExposedPorts.
  • internal/sandbox/linux.go: resolv.conf guard fix (+ TODO noting mountinfo-based shape); emits --ro-bind/--bind for ExposedHostPaths after tmpfs mounts; corrected misleading "non-recursive" comment on --ro-bind / /.
  • internal/sandbox/macos.go: folds ExposedHostPaths into seatbelt read/write allowlists.
  • internal/sandbox/linux_stub.go: stub parity for ExposedHostPaths.
  • pkg/fence/fence.go: re-exports ServiceOptions, ServiceExecutionModel, enum constants.
  • cmd/fence/main.go: new --service-execution-model, --expose-host-path, --expose-host-path-rw flags.
  • Tests: manager_test.go (new) covers the API; linux_test.go adds two regression guards (exposed path under /tmp is bound AFTER --tmpfs /tmp).
  • docs/library.md updated.

Breaking

  • Manager.SetExposedPorts removed. Callers migrate to Manager.SetService(ServiceOptions{ExposedPorts: ...}). Default execution model (ServiceBindsInSandbox) preserves historical behavior.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="internal/sandbox/macos.go">

<violation number="1" location="internal/sandbox/macos.go:668">
P2: Writable exposed host paths are not added to the read allowlist, so `ExposeHostPath(..., true)` can still be unreadable when `defaultDenyRead` is enabled.</violation>
</file>

<file name="internal/sandbox/manager.go">

<violation number="1" location="internal/sandbox/manager.go:113">
P2: Validate that ExposeHostPath targets an existing host path before accepting it; currently invalid paths are accepted and later ignored.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread internal/sandbox/macos.go
Comment thread internal/sandbox/manager.go
@jy-tan jy-tan merged commit 2bc292f into main Apr 24, 2026
6 checks passed
@jy-tan jy-tan deleted the docker-fix branch April 24, 2026 20:26
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