Skip to content

feat(sandbox): support gated host mounts through driver_config #1760

Description

@elezar

Problem Statement

OpenShell sandboxes currently have no first-class way to request live host
filesystem mounts through the driver-specific sandbox configuration path. The
existing sandbox upload and sandbox download flows are copy-based, which is
safe and portable but does not cover long-running workflows that need a live,
read-only view of host data such as repositories, local reference data,
diagnostic artifacts, or operator-provided shared directories.

Historically, host mounts have been rejected or deferred because they are
security-sensitive and driver-specific. That concern still applies. The new
SandboxTemplate.driver_config passthrough proposal gives us a better boundary:
the public API can stay generic, the gateway can remain driver-agnostic, and
each compute driver can own validation and rendering for its own runtime.

The missing design is a common, safe-by-default host_mounts schema under
driver_config, with driver-level admin gates, allowlisted host prefixes, and
read-only behavior by default.

Proposed Design

Add a driver-owned host_mounts schema under the active driver's
containers.agent config:

{
  "kubernetes": {
    "containers": {
      "agent": {
        "host_mounts": [{
          "name": "shared-data",
          "host_path": "/var/lib/openshell/shared",
          "mount_path": "/mnt/shared",
          "type": "Directory"
        }]
      }
    }
  },
  "docker": {
    "containers": {
      "agent": {
        "host_mounts": [{
          "name": "shared-data",
          "host_path": "/var/lib/openshell/shared",
          "mount_path": "/mnt/shared"
        }]
      }
    }
  },
  "podman": {
    "containers": {
      "agent": {
        "host_mounts": [{
          "name": "shared-data",
          "host_path": "/var/lib/openshell/shared",
          "mount_path": "/mnt/shared"
        }]
      }
    }
  }
}

Field semantics:

  • name: required logical name, valid for the active driver and unique within
    the request.
  • host_path: required absolute path on the compute host.
  • mount_path: required absolute path inside the agent workload.
  • read_write: optional, defaults to false. Omit it for read-only mounts.
    read_write: true should be rejected in the first implementation unless the
    active driver has an explicit read-write admin gate.
  • type: optional and driver-specific. Kubernetes maps this to
    hostPath.type; Docker and Podman should reject non-empty values initially
    unless they implement equivalent validation.

Add driver config gates:

[openshell.drivers.kubernetes]
allow_host_path_mounts = false
host_path_mount_allowed_prefixes = ["/var/lib/openshell/shared"]

[openshell.drivers.docker]
allow_host_path_mounts = false
host_path_mount_allowed_prefixes = ["/var/lib/openshell/shared"]

[openshell.drivers.podman]
allow_host_path_mounts = false
host_path_mount_allowed_prefixes = ["/var/lib/openshell/shared"]

First-pass behavior:

  • Reject host_mounts unless the active driver has
    allow_host_path_mounts = true.
  • Reject all paths if the active driver's allowed-prefix list is empty.
  • Match allowed prefixes on path components, not raw string prefixes.
  • Render mounts read-only by default.
  • Reject read_write: true unless a future explicit
    allow_read_write_host_path_mounts gate is added.
  • Validate and fail fast during ValidateSandboxCreate and again before
    rendering during CreateSandbox.

Driver rendering:

  • Kubernetes: render accepted mounts as hostPath volumes plus volumeMounts
    on the agent container. Set readOnly: !read_write.
  • Docker: render accepted mounts through HostConfig.binds, following the
    existing internal bind style for read-only mounts.
  • Podman: render accepted mounts through the existing mounts array as bind
    mounts with ["ro", "rbind"], plus z when SELinux is enabled.
  • VM: reject driver_config.vm.containers.agent.host_mounts for now with a
    clear unsupported message. VM support needs a separate transport decision
    such as virtiofs, 9p, or an extra block image, plus guest init integration.

Validation should reject:

  • malformed host_mounts;
  • duplicate mount names or target paths;
  • non-absolute or non-normalized host_path / mount_path;
  • host paths outside allowed prefixes;
  • reserved OpenShell mount targets such as /sandbox,
    /var/run/secrets/openshell, /run/netns, TLS mount directories, and
    supervisor mount directories;
  • unsupported driver-specific type values;
  • read_write: true until writable mounts have a separate security design.

Documentation should cover Docker Desktop and Podman machine path-resolution
semantics: paths are resolved by the daemon/VM host, not necessarily the
gateway process filesystem.

Alternatives Considered

  • Public typed protobuf mount fields: rejected for the first pass because host
    mounts are driver-specific and should not force a lowest-common-denominator
    API.
  • Provider-driven mounts: rejected because providers are credential/config
    records, not filesystem access grants.
  • Arbitrary pod/container spec passthrough: rejected because it makes security
    review and validation too broad.
  • sandbox upload / sandbox download: safe and portable, but copy-based and
    not a live filesystem view.
  • VM virtiofs support now: useful, but it requires separate VM runtime and
    guest-init design. This proposal should reject VM host mounts until that work
    is intentionally designed.

Agent Investigation

Local codebase findings:

  • SandboxTemplate.driver_config exists on the public API and is forwarded as
    the selected driver block to DriverSandboxTemplate.driver_config.
  • crates/openshell-server/src/compute/mod.rs selects the active driver block
    and keeps the gateway out of nested schema validation.
  • crates/openshell-driver-kubernetes/src/driver.rs already decodes
    driver-local config for pod scheduling and agent resources, and already
    renders managed volumes/mounts for TLS, ServiceAccount bootstrap, supervisor
    sideloading, and workspace persistence.
  • crates/openshell-driver-docker/src/lib.rs already builds driver-owned bind
    mounts for the supervisor binary, TLS files, and sandbox token through
    HostConfig.binds.
  • crates/openshell-driver-podman/src/container.rs already renders bind mounts
    for TLS/token files and has SELinux-aware mount options.
  • crates/openshell-driver-vm/src/driver.rs currently rejects
    platform_config; VM host sharing needs a transport and guest mount design
    before support can be claimed.

Related issues and PRs:

Definition of Done

  • Add driver config gates and allowlists for Kubernetes, Docker, and Podman.
  • Add typed host-mount parsing/validation for Kubernetes, Docker, and
    Podman driver config.
  • Render read-only host mounts for Kubernetes, Docker, and Podman.
  • Reject VM host mount config with a clear unsupported error.
  • Add unit tests for success, disabled gates, disallowed prefixes,
    duplicate names/targets, reserved targets, unsupported types, read-write
    rejection, and VM unsupported behavior.
  • Update driver READMEs and reference docs.
  • Update Helm values/rendering/tests for the Kubernetes gate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions