bug: enableUserNamespaces causes sandbox creation to fail with "setgroups: Invalid argument"
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
Agent Diagnostic
Skills loaded: debug-openshell-cluster create-github-issue
Investigation findings:
- Confirmed the user namespace feature exists (
enableUserNamespacesin Helm values, added in commit1f35abbe) - Traced configuration flow: Helm → gateway TOML → Kubernetes driver → pod spec (
hostUsers: false) - Located root cause in
crates/openshell-supervisor-process/src/process.rs:1431 - Verified no fix exists in current
mainbranch - Checked latest release: v0.0.92 (2026-07-27) - bug present
- Searched existing issues: No duplicate found
- Issue #1597: Different issue (E2E test setup)
- Issue #982: Original feature request (closed, implemented in
1f35abbe) - Issue #622: Related
initgroupsissue for tests only, not runtime
Testing confirmation:
- Tested on OpenShift with
enableUserNamespaces=false: ✅ SUCCESS - Tested on OpenShift with
enableUserNamespaces=true: ❌ FAILS with "setgroups: Invalid argument"
Root cause analysis:
When server.enableUserNamespaces=true, the Kubernetes driver correctly sets hostUsers: false and adds SETUID/SETGID capabilities. However, the supervisor's drop_privileges() function unconditionally calls initgroups() when dropping to a named user identity.
In Kubernetes user namespaces (hostUsers: false):
- Container runtime creates user namespace and writes
/proc/<pid>/gid_map - Kernel sets
/proc/<pid>/setgroupsto "deny" (privilege escalation prevention) - Once
gid_mapis written,/proc/self/setgroupscannot be changed to "allow" - Supervisor calls
initgroups()→ internally callssetgroups()→ fails withEINVAL - Container exits during startup
Technical details:
- File:
crates/openshell-supervisor-process/src/process.rs - Line: 1431 -
nix::unistd::initgroups(user_cstr.as_c_str(), target_gid).into_diagnostic()?; - Call is only skipped on macOS/iOS/Haiku/Redox, not for Linux user namespaces
- No detection of
/proc/self/setgroupsrestriction exists
Proposed fix:
Before calling initgroups(), check if /proc/self/setgroups contains "deny". If so, skip the initgroups() call. In user namespace context, supplementary groups are already appropriately isolated, so skipping is safe.
Note: Original feature commit 1f35abbe claimed validation on OCP 4.22, but current testing shows the feature is broken on OpenShift.
Description
Actual behavior: When deploying OpenShell with --set server.enableUserNamespaces=true, all sandbox creation attempts fail during container startup with Error: container create failed: setgroups: Invalid argument.
Expected behavior: Sandboxes should start successfully with user namespace isolation enabled, providing defense-in-depth by mapping container UID 0 to an unprivileged host UID.
Reproduction Steps
-
Deploy with user namespaces enabled:
helm install openshell deploy/helm/openshell \ --namespace openshell \ --create-namespace \ --set server.enableUserNamespaces=true \ --wait -
Attempt to create a sandbox:
openshell sandbox create --name test -
Observe failure:
Created sandbox: test ✓ Sandbox allocated (3s) ✓ Image pulled (8s) ⠄ Starting sandbox... Error: container create failed: setgroups: Invalid argument (5s)
Environment
- OS: OpenShift / Kubernetes with user namespace support (1.33+)
- Container runtime: containerd 2.0+ or cri-o 1.25+
- OpenShell: v0.0.92 (latest release)
- Latest release checked: yes (v0.0.92)
- Possible duplicates checked: yes (issues #1597, #982, #622 reviewed - none match)
- Tested platforms: OpenShift (confirmed broken with flag enabled, works with flag disabled)
Logs
Expected container logs when inspecting the failed sandbox pod:
Error: setgroups: Invalid argument
Kernel behavior:
# Inside a user namespace pod (hostUsers: false)
$ cat /proc/self/setgroups
deny
# Attempting setgroups() in this state returns EINVAL
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in crates/openshell-supervisor-process/src/process.rs at drop_privileges(), especially line 1431 where initgroups() is called. Reproduce with server.enableUserNamespaces=true and inspect /proc/self/setgroups; done means sandbox creation succeeds in a user namespace while the existing non-user-namespace behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- helm, kubernetes, rust
- Domain
- infrastructure, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100