Repository navigation
feat: honor OCI WorkingDir for Docker and Podman workspaces #2526
Description
Activity
- addedarea:sandboxSandbox runtime and isolation workSandbox runtime and isolation work
on Jul 28, 2026 🏗️ build-plan
Implementation Plan
Issue type:
feat
Complexity: Medium
Confidence: High — RFC 0012 provides the required separation, and the Docker/shared workspace plumbing is already present.Summary
Implement the remaining Podman half of OCI
WORKDIRsupport against the RFC 0012 isolation architecture. ResolveConfig.WorkingDirfrom the same pinned inspection as image identity and environment. Keep a custom workspace in the workload container's writable layer, without a workspace volume or copy-up. Pass its root through the existing supervisor--workdirpath. Empty,/, and explicit/sandboxdeclarations retain the managed/sandboxfallback.Scope
crates/openshell-driver-podman/src/client.rs: deserialize and test OCIWorkingDiralongsideUserandEnv.crates/openshell-driver-podman/src/container.rs: group the requested reference, immutable ID, user, environment, and resolved workspace in image metadata; validate workspace/mount/control-path collisions; distinguish managed/sandboxfrom custom image directories; start trusted runtime binaries from/and pass the workspace to agent processes.crates/openshell-driver-podman/src/driver.rs: resolve metadata before resource creation; create and initialize the owned workspace volume only for managed/sandbox.- Focused Podman unit tests and
e2e/rust/tests/podman_oci_identity.rs: cover immutable pinning, custom cwd/write access, image-file and ownership preservation, fallback, and mount collisions. Shared Docker/Podman OCI behavior coverage belongs to fix(oci): report workspace rejections and share OCI USER and WORKDIR checks across Docker and Podman #3931. - Podman README, published runtime docs, and relevant operator skills: document workspace selection and the container-lifetime persistence contract.
Implementation Steps
- Inspect the immutable workload image once and bind its requested reference, image ID, user, environment, and working directory in resolved metadata. Empty,
/, and explicit/sandboxselect managed/sandbox. - Reject malformed workspace declarations, runtime/control-path overlaps, and image-declared volumes or driver mounts that cover the workspace. Continue allowing mounts nested below it.
- Create and initialize the workspace volume only for the managed fallback. Keep custom workspaces in the workload container's writable layer; do not create, chown, chmod, or copy their contents into a volume.
- Start trusted runtime binaries from
/so Podman does not create or enter a custom workspace before validation. Pass the resolved path through the existing supervisor--workdirmechanism for agent processes. - Validate the custom directory's effective traversal and write access as the final non-root workload identity before launching agent code. Reject an unusable workspace without requiring a particular condition reason.
- Document writable-layer persistence and validate shared OCI behavior on Docker and both Podman lanes in fix(oci): report workspace rejections and share OCI USER and WORKDIR checks across Docker and Podman #3931.
Test Plan
- Unit: image-inspect parsing; fallback and invalid declarations; pinned launch metadata; supervisor argv; trusted container cwd; mount collision directionality; managed-volume creation versus custom-directory launch; conditional workspace archive upload.
- Integration: Podman create-spec serialization remains pinned to the inspected image ID while carrying the resolved workspace and original reference as metadata.
- E2E: a pre-populated owner-only custom
WORKDIR; verify cwd/write access, existing image files, root-owned file preservation, directory identity/mode, immutable image launch, and absence of a managed workspace mount. Keep managed/sandboxcoverage without a baked directory. - Shared coverage (fix(oci): report workspace rejections and share OCI USER and WORKDIR checks across Docker and Podman #3931): Docker/Podman workspace behavior, rejection of an unwritable directory without requiring
WorkspaceValidationFailed, persistence across stop/start of the same container, and no transfer of changes to a replacement container. Keep fallback and nested-mount checks.
Persistence Contract and Risks
- Custom workspace contents survive normal stop/start of the same workload container. Removing or replacing that container removes workspace changes; a new sandbox starts with the image's original files. Export files that must outlive the sandbox before deletion.
- Custom directories retain the image's ownership and permissions. The final identity must be able to traverse and write them; OpenShell does not repair them. No named-volume copy-up is involved for custom roots.
- Workspace validation runs in the capability-free sandbox runtime before untrusted execution. No pre-RFC probe container, privileged repair step, identity attestation, or new protobuf plumbing is introduced.
- Driver mount validation uses structured paths after image inspection, not shell construction.
- Cross-runtime
HOMEbehavior stays in feat: define cross-runtime agent HOME behavior #3873; image-declared volume resource admission stays in bug(podman): resource admission rejects image-declared VOLUMEs; lacks Docker parity #3890. Cross-driver failure-classification improvements are not a prerequisite for WORKDIR support.
Documentation Impact
Update the Podman crate README, published runtime guide, and operator/debug guidance. Explain that custom workspaces use the container's writable layer and that the
/sandboxfallback remains managed. No gateway TOML, driver option, Helm rendering, or default changes are introduced.Current PRs
- fix(podman): create managed workspace volumes owned by the workload identity #3981: managed Podman
/sandboxownership fix (merged). - feat(podman): honor OCI image working directories #3982: focused Podman OCI WORKDIR support.
- fix(oci): report workspace rejections and share OCI USER and WORKDIR checks across Docker and Podman #3931: shared Docker/Podman OCI behavior tests, stacked on feat(podman): honor OCI image working directories #3982.
These supersede the earlier implementation in #3801.
Revision 3 — custom workspaces use the workload container's writable layer; replaces the named-volume/copy-up design and documents container-lifetime persistence.
Revision 2 — redesigned for RFC 0012 supervisor/workload separation.
Revision 1 — initial stacked implementation plan.- addedstate:review-readyReady for human reviewReady for human reviewstate:agent-readyApproved for agent implementationApproved for agent implementationstate:in-progressWork is currently in progressWork is currently in progressstate:pr-openedPR has been opened for this issuePR has been opened for this issueand removedstate:review-readyReady for human reviewReady for human reviewstate:in-progressWork is currently in progressWork is currently in progress
on Jul 28, 2026 Implementation is available in stacked PR #2530 (based on #2509).
Implemented OCI WorkingDir resolution for Docker/Podman, consistent supervisor cwd/HOME and workspace preparation, dynamic
include_workdirpolicy handling, Podman workspace-volume placement, SSH-discovered CLI transfer/editor roots, focused tests, and documentation updates.Validation completed:
mise run pre-commitmise run test- focused Docker
custom_imageE2E - focused Docker
driver_config_volumeE2E
Live Podman E2E was unavailable locally; Podman inspect/spec/copy-up behavior is covered by focused unit tests.
- added 5 commits that reference this issue
on Jul 28, 2026 This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.
- addedstate:staleInactive item at risk of automatic closure.Inactive item at risk of automatic closure.
on Aug 12, 2026 🏗️ build-from-issue-agent
Implementation Ready — E2E Blocked
The RFC 0012-aligned Podman WORKDIR implementation is complete on branch
codex/2526-podman-workdir-rfc12at commite073caa915d8c3bd1e0015f523c5cb4717c845d4.Verification
mise run pre-commit: passed- Podman driver unit tests: 234 passed
- Focused Podman E2E targets: compile and Clippy passed
mise run ci: Podman tests passed; the workspace task stopped on five unrelated VM-driver tests because this host does not havemke2fsormkfs.ext4mise run e2e:podman:ci: blocked before tests because the localpodman-machine-defaultVM exits immediately after startup and its API endpoint refuses connections
The required live Podman E2E gate is not green, so no pull request was opened. The branch is pushed for recovery or verification on a healthy Podman host.
- removedstate:staleInactive item at risk of automatic closure.Inactive item at risk of automatic closure.
on Sep 29, 2026
Problem Statement
Follow-up to #2331 and stacked on #2509.
#2331 removes the requirement for Docker and Podman images to contain a
sandbox:sandboxaccount, but intentionally keeps/sandboxas OpenShell'sfixed workspace. OCI images can already declare their intended workspace with
Config.WorkingDir; ignoring it means off-the-shelf images may still requireOpenShell-specific
/sandboxpreparation, 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
Config.WorkingDiralongsideConfig.Userfrom the same immutable image inspected by feat: preserve image-declared identity in Docker and Podman #2331.
WorkingDirwhen it is non-empty and not/./, or explicit/sandboxdeclaration, use/sandboxas an OpenShell-createdfallback. The image does not need to contain or pre-own it.
custom workspace root that is missing, resolves to a symlink or
non-directory, or cannot be traversed and written by the final workload
identity. Do not create it or change its ownership or permissions.
/sandbox.This is an internal runtime decision, not a new public setting or gateway
configuration field.
Runtime behavior
do not add a new supervisor flag or identity protocol.
/sandboxfallback for the final effective UID/GID.Validate custom directories as that identity before launching agent code.
/so Podman does not create or enter acustom workspace before validation; agent processes use the resolved root as
their cwd.
HOMEcontract in feat: define cross-runtime agent HOME behavior #3873; this change does not add anew HOME requirement.
filesystem.include_workdiris true./sandboxas a baseline filesystempath. User-authored policy entries that explicitly name
/sandboxremainliteral and are never rewritten.
Driver behavior
inspected by Docker and Podman.
/sandboxfallback. Custom workspaces remain in the workload container'swritable layer, with no workspace volume or ownership-setting archive.
workspace, and reject runtime/control-path overlaps after image inspection.
Continue allowing mounts nested below the workspace.
copy-up or directory repair.
Removing or replacing that container removes its workspace changes; a new
sandbox starts from the image's original files. Export files that must be
retained before deleting the sandbox.
CLI behavior
Use the existing SSH connection to discover the canonical remote workspace with
pwd -P; avoid adding a publicworkspace_rootstatus field unless anon-SSH consumer proves it necessary.
a hardcoded
/sandbox.rather than relying on SSH
~.Alternatives Considered
/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.
/sandbox: retained as the empty//fallback and for explicit/sandboxdeclarations. Itpreserves compatibility but should not override a usable OCI
WorkingDir.choose its managed-volume target before the supervisor can resolve
/etc/passwd. A driver-known fallback is simpler and deterministic.WorkingDir: not selected. Keep theimage directory in the container's writable layer without copy-up or
ownership changes, with persistence tied to that container's lifetime.
workspace_rootfield: avoid initially because theaffected CLI operations already establish SSH sessions and can discover the
canonical cwd directly.
/sandboxpolicy paths: rejected. Explicit policypaths must retain their literal meaning.
Definition of Done
WorkingDir, with driver-created/sandboxfallback for empty,/, or explicit/sandboxdeclarations.cross-runtime
HOMEcontract remains a separate follow-up (feat: define cross-runtime agent HOME behavior #3873).include_workdirgrants the resolved root without rewriting explicitpolicy paths.
workspace-covering volume. Changes persist across stop/start of the same
container, with the container-lifetime limit documented.
custom workspace root; nested mounts remain valid.
SSH-discovered workspace root.
/sandboxbehavior.launch flag is introduced.
Test Plan
WorkingDir: absolute named path, absent,/, relative, malformed,missing, pre-populated, symlink, non-directory, and read-only.
/sandbox.feat: define cross-runtime agent HOME behavior #3873 rather than required by this change.
include_workdirfollows the resolved root; explicit/sandboxremains literal.
mount. Changes survive stop/start of the same container and do not transfer
to a replacement container.
discovered root.
Agent Investigation
DockerImageMetadataand Podman'sImageInspectalready bind OCIConfig.Userto immutable image launch, soConfig.WorkingDircan be read inthe same inspection.
launch, SSH process launch, and Landlock preparation.
/sandbox./sandbox./sandbox; uploadwithout 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/
fsGroupbehavior, change VM guest initialization, or fold thiswork back into #2509. Keep cross-runtime
HOMEbehavior in #3873 andimage-declared volume resource admission in #3890. A distinct
WorkspaceValidationFailedcondition reason is not required; an unusableworkspace must still be rejected.
Checklist
Current Implementation
The remaining Podman WORKDIR implementation is in #3982, with shared
Docker/Podman OCI behavior tests in #3931. The managed
/sandboxownership fixlanded in #3981. These supersede the earlier approach in #3801.