User Story
As someone creating a sandbox from an off-the-shelf image,
I want the error to say that the image runs as root and what I can do about it,
so that I can fix it without having to read OpenShell source code.
Problem Statement
OpenShell never runs a workload as root. When the policy doesn't set process.run_as_user, the Docker driver takes the identity from the image's USER, so an image that declares USER root is rejected. That's intended and documented in docs/how-it-works/policies/default-policy.mdx. The error message could be improved:
IdentityResolutionFailed: descriptor error: workload identity must not contain UID or GID zero
It doesn't say the zero came from the image's USER, it doesn't suggest a fix, and descriptor error is an internal name. The CLI also prints it twice.
From reading the code, a non-root user listed as a member of group 0 in the image's /etc/group gets the same error. Setting run_as_group alone doesn't fix it: the user still belongs to group 0 through the image's /etc/group.
Two related things I found:
- Docker defaults to root both when the image has no
USER and when it explicitly declares USER root. OpenShell instead uses 1000:1000 for the first case and rejects the second.
docs/how-it-works/sandboxes/runtimes.mdx says images without USER must set both policy fields. The code and default-policy.mdx say they fall back to 1000.
#3653 asks for regression tests on the same root rejection. This issue is about the error message.
Impact / Why This Matters
The error comes after the image pull, and it names neither the image nor a fix. Reading crates/openshell-driver-docker/src/lib.rs shows that the image's USER was the cause.
As an end user, the workaround is to build a derived image with a non-root USER, or to set run_as_user and run_as_group in a policy file. Neither is discoverable from the error.
For netshoot the policy route gets past identity resolution and then fails workspace validation: its WORKDIR is /root, which is drwxrwx--- root root in the image, so UID and GID 1000 can't enter it. That's a separate problem and not part of this issue.
Acceptance Criteria
Reproduction Steps
openshell sandbox create --name test-sandbox --detach --from nicolaka/netshoot:latest
- It fails with "IdentityResolutionFailed".
docker image inspect nicolaka/netshoot:latest --format '{{.Config.User}}' shows root.
Environment
- OpenShell 0.1.2 (Homebrew) on macOS 26.2 arm64, local Docker gateway. The identity code and both docs pages are the same on
main at 021400be8.
- Docker Engine 29.4.0 (linux/arm64)
Logs
$ openshell sandbox create --name test-sandbox --detach --from nicolaka/netshoot
Created sandbox: test-sandbox
✗ Error: IdentityResolutionFailed: descriptor error: workload identity must not contain UID or GID zero
✓ Sandbox allocated (0s)
✓ Image pulled (0s) Error: × sandbox entered error phase while provisioning: IdentityResolutionFailed: descriptor error: workload identity must not
│ contain UID or GID zero
User Story
As someone creating a sandbox from an off-the-shelf image,
I want the error to say that the image runs as root and what I can do about it,
so that I can fix it without having to read OpenShell source code.
Problem Statement
OpenShell never runs a workload as root. When the policy doesn't set
process.run_as_user, the Docker driver takes the identity from the image'sUSER, so an image that declaresUSER rootis rejected. That's intended and documented indocs/how-it-works/policies/default-policy.mdx. The error message could be improved:It doesn't say the zero came from the image's
USER, it doesn't suggest a fix, anddescriptor erroris an internal name. The CLI also prints it twice.From reading the code, a non-root user listed as a member of group 0 in the image's
/etc/groupgets the same error. Settingrun_as_groupalone doesn't fix it: the user still belongs to group 0 through the image's/etc/group.Two related things I found:
USERand when it explicitly declaresUSER root. OpenShell instead uses1000:1000for the first case and rejects the second.docs/how-it-works/sandboxes/runtimes.mdxsays images withoutUSERmust set both policy fields. The code anddefault-policy.mdxsay they fall back to 1000.#3653 asks for regression tests on the same root rejection. This issue is about the error message.
Impact / Why This Matters
The error comes after the image pull, and it names neither the image nor a fix. Reading
crates/openshell-driver-docker/src/lib.rsshows that the image'sUSERwas the cause.As an end user, the workaround is to build a derived image with a non-root
USER, or to setrun_as_userandrun_as_groupin a policy file. Neither is discoverable from the error.For netshoot the policy route gets past identity resolution and then fails workspace validation: its
WORKDIRis/root, which isdrwxrwx--- root rootin the image, so UID and GID 1000 can't enter it. That's a separate problem and not part of this issue.Acceptance Criteria
USER, its/etc/passwdor/etc/group, or the policy).USER, the error names the image and says to use a non-root image or setprocess.run_as_userandrun_as_group.descriptor errordoesn't appear in the message.runtimes.mdxmatchesdefault-policy.mdxand the code for images with noUSER.USERand no policy identity still gets1000:1000.Reproduction Steps
openshell sandbox create --name test-sandbox --detach --from nicolaka/netshoot:latestdocker image inspect nicolaka/netshoot:latest --format '{{.Config.User}}'showsroot.Environment
mainat021400be8.Logs
$ openshell sandbox create --name test-sandbox --detach --from nicolaka/netshoot Created sandbox: test-sandbox ✗ Error: IdentityResolutionFailed: descriptor error: workload identity must not contain UID or GID zero ✓ Sandbox allocated (0s) ✓ Image pulled (0s) Error: × sandbox entered error phase while provisioning: IdentityResolutionFailed: descriptor error: workload identity must not │ contain UID or GID zero