Skip to content

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

@elezar

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
    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