Skip to content

feat: honor OCI WorkingDir for Docker and Podman workspaces #2526

Description

@matthewgrossman

Problem Statement

Follow-up to #2331 and stacked on #2509.

#2331 removes the requirement for Docker and Podman images to contain a
sandbox:sandbox account, but intentionally keeps /sandbox as OpenShell's
fixed workspace. OCI images can already declare their intended workspace with
Config.WorkingDir; ignoring it means off-the-shelf images may still require
OpenShell-specific /sandbox preparation, and direct sessions, SSH sessions,
filesystem policy, persistence, transfers, and editor launch can disagree about
the effective workspace.

Docker and Podman should honor the image-declared working directory without
changing Kubernetes/OpenShift or VM workspace behavior.

Proposed Design

Introduce one internal resolved workspace root and use it consistently across
the local container drivers, supervisor, policy runtime, and SSH-based CLI
operations.

Resolution

  1. Docker and Podman inspect OCI Config.WorkingDir alongside Config.User
    from the same immutable image inspected by feat: preserve image-declared identity in Docker and Podman #2331.
  2. Use a normalized absolute WorkingDir when it is non-empty and not /.
  3. For an empty or / declaration, use /sandbox as an OpenShell-created
    fallback. The image does not need to contain or pre-own it.
  4. Reject malformed non-empty declarations, including relative paths. Reject a
    workspace root that resolves to a symlink, non-directory, or otherwise
    cannot be safely created and owned.
  5. Kubernetes/OpenShift and VM continue resolving their workspace root to
    /sandbox.

This is an internal runtime decision, not a new public setting or gateway
configuration field.

Runtime behavior

  • Pass the resolved root through the supervisor's existing workdir mechanism;
    do not add a new supervisor flag or identity protocol.
  • Prepare the resolved directory for the final effective UID/GID before
    readiness.
  • Use the same root as the cwd and workspace HOME for direct and SSH children.
  • Feed the resolved root to Landlock when filesystem.include_workdir is true.
  • Stop automatically injecting literal /sandbox as a baseline filesystem
    path. User-authored policy entries that explicitly name /sandbox remain
    literal and are never rewritten.

Driver behavior

  • Pin both identity and workspace resolution to the immutable image ID already
    inspected by Docker and Podman.
  • Mount Podman's managed workspace volume at the resolved root instead of
    unconditionally at /sandbox.
  • Reserve the resolved workspace root from Docker/Podman driver-config mounts
    after image inspection. Preserve all other mount behavior.
  • Confirm and preserve Podman named-volume copy-up behavior when WorkingDir
    already contains image files.

CLI behavior

Use the existing SSH connection to discover the canonical remote workspace with
pwd -P; avoid adding a public workspace_root status field unless a
non-SSH consumer proves it necessary.

  • Download containment and symlink checks use the discovered root rather than
    a hardcoded /sandbox.
  • Upload without an explicit destination extracts into the discovered root
    rather than relying on SSH ~.
  • Editor launch opens the discovered remote root.

Alternatives Considered

  • Recursively chown /sandbox: rejected in feat(sandbox): use policy-first OCI image identity #2509. It mutates image content,
    risks crossing ownership boundaries, and treats the symptom rather than
    honoring OCI workspace metadata.
  • Always use /sandbox: retained only as the empty// fallback. It
    preserves compatibility but should not override a usable OCI WorkingDir.
  • Use the OCI user's account home as fallback: rejected because Podman must
    choose its managed-volume target before the supervisor can resolve
    /etc/passwd. A driver-known fallback is simpler and deterministic.
  • Add a public gateway workspace_root field: avoid initially because the
    affected CLI operations already establish SSH sessions and can discover the
    canonical cwd directly.
  • Rewrite user-authored /sandbox policy paths: rejected. Explicit policy
    paths must retain their literal meaning.

Definition of Done

  • Docker and Podman use a valid OCI WorkingDir, with driver-created
    /sandbox fallback for empty or /.
  • Direct and SSH children share the resolved cwd/HOME and can write there.
  • include_workdir grants the resolved root without rewriting explicit
    policy paths.
  • Podman persistence mounts at the resolved root and preserves expected
    image-content copy-up.
  • Driver-config mounts cannot replace the resolved workspace root.
  • Upload defaults, download containment, and editor launch use the
    SSH-discovered workspace root.
  • Kubernetes/OpenShift and VM retain their current /sandbox behavior.
  • No public workspace setting, gateway schema field, or new supervisor
    launch flag is introduced.

Test Plan

  • OCI WorkingDir: absolute named path, absent, /, relative, malformed,
    missing, pre-populated, symlink, non-directory, and read-only.
  • Driver-owned fallback works without image-prepared /sandbox.
  • Direct and SSH identity, cwd, HOME, and write behavior agree.
  • Landlock include_workdir follows the resolved root; explicit /sandbox
    remains literal.
  • Podman persistence and copy-up target the resolved root.
  • Nested/user mounts retain their ownership and existing behavior.
  • Upload, download traversal/symlink protection, and editor launch use the
    discovered root.
  • Kubernetes/OpenShift and VM regression coverage remains unchanged.

Agent Investigation

  • Searched open and closed issues; found no duplicate OCI WorkingDir proposal.
  • Docker's DockerImageMetadata and Podman's ImageInspect already bind OCI
    Config.User to immutable image launch, so Config.WorkingDir can be read in
    the same inspection.
  • The supervisor already accepts and threads a workdir through direct process
    launch, SSH process launch, and Landlock preparation.
  • Podman's managed workspace volume is currently hardcoded to /sandbox.
  • Mount validation currently reserves literal /sandbox.
  • CLI download guards and editor launch currently hardcode /sandbox; upload
    without a destination currently relies on the SSH home directory.

Scope Boundaries

Do not redesign OCI identity from #2331, add a public workspace setting, change
Kubernetes PVC/fsGroup behavior, change VM guest initialization, or fold this
work back into #2509.

Checklist

  • I've reviewed existing issues and the architecture docs
  • This is a design proposal, not a "please build this" request

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:sandboxSandbox runtime and isolation workstate:agent-readyApproved for agent implementationstate:pr-openedPR has been opened for this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions