Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Actor rootfs `/` is mode 0700, so non-root users cannot traverse the root filesystem

Open Beginner friendly
#2,035 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
go, linux

Research direction

Start in internal/imagecache/bundle_linux.go:61-66 and inspect how rootfs, upper, and work are created before the overlay mount at line 81. Read applyDirFixups in internal/imagecache/implicitdirs.go to determine whether the merged root is handled. Done means a standard image root remains traversable by non-root users, with a regression check for the reported 0700 root behavior.

Written by the indexing model from the issue text.

Description

area/gvisor area/node kind/bug

Summary

Inside a gVisor actor, the root directory / is root:root 0700. A workload that drops to a non-root user cannot resolve any path at all, not even /bin/sh, because the first path component is not traversable. Docker and containerd keep the image root's mode (normally 0755). As shipped, any non-root workload fails on Substrate.

Impact

  • Who hits it: every integrator whose workload runs as, or switches to, a non-root user. Agent runtimes and most hardened images do this.
  • What breaks: su, runuser and any exec as a non-root uid fail with Permission denied. The workload cannot start.
  • Cost: each integrator has to add a root-privileged fixup at actor start.
  • Severity: High.
  • Proposed priority: P1. It blocks non-root workloads out of the box. A workaround exists but needs root at startup, which depends on the uid-0 start (see Workload has no user field or no-new-privileges setting…).

Environment

  • Substrate d277088b (v1alpha).
  • GKE 1.36.x.
  • gVisor sandbox class, unprivileged WorkerPool workers.

Steps to reproduce / evidence

  1. Create the actor (verified live). Use an ActorTemplate whose image is a Debian-based image with a non-root user (for example useradd -u 1000 agent). Create an actor from it.
  2. Check the root mode inside the actor, as root (verified live):
    $ stat -c '%a:%U:%G %n' /
    700:root:root /
    
  3. Switch to the non-root user (verified live):
    $ su agent -s /bin/sh -c id
    su: failed to execute /bin/sh: Permission denied
    
    /bin/sh is itself 0755. The failure is at the traversal of /.
  4. Show that a 0755 root is sufficient (verified live). After chmod 755 / (as root), su and runuser to the non-root uid both succeed. The same test also chowned the user's home directory; the exec itself (su … -c id) depends only on / being traversable.
  5. Cause (code-read at d277088b):
    • internal/imagecache/bundle_linux.go:61-66 creates <bundle>/rootfs, upper and work with os.MkdirAll(d, 0o700).
    • The overlay is then mounted at rootfs with that upperdir (bundle_linux.go:81).
    • The merged overlay root takes its attributes from the upperdir root.
    • applyDirFixups in internal/imagecache/implicitdirs.go repairs implicit parent directories. It does not appear to cover / itself.

Expected vs actual

  • Expected: the actor's / has the image root's mode (0755 for standard base images), as under Docker, containerd and Kubernetes.
  • Actual: / is 0700 and owned by root. No non-root uid can traverse it.

Workaround

At actor start, while still uid 0, an integrator can:

  1. chmod 755 / if / is more restrictive than that.
  2. Check that the workload user can traverse the rootfs (for example that /bin/sh resolves).
  3. Fail closed if it cannot.

This only works because the workload starts as root.

Additional detail

  • Suggested fix: create the bundle rootfs/upperdir root with 0755, or copy the image root's mode onto it after the overlay is mounted.
  • Related issues (same class, image metadata lost in the actor rootfs):
    • Image-layer file ownership appears as uid 0 inside the actor (image-layer-file-ownership-lost.md).
    • Actor rootfs drops setuid, setgid and sticky bits from image layers (/tmp is 0777) (actor-rootfs-drops-special-mode-bits.md).
Dominant language
Go
Stars
4.4k
Forks
515
Avg merge
2d 10h
Merged PRs (30d)
295

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from agent-substrate/substrate

All issues in agent-substrate/substrate

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.