slim currently ignores the USER directive from the image config. The VM's init and the container's CMD/ENTRYPOINT always run as root (uid 0), regardless of any USER directive in the Dockerfile.
still boots with id reporting uid=0(root) inside the VM.
Root cause
The OCI image config exposes .Config.User (populated by the USER Dockerfile directive), but slim never reads it:
src/inject.rs:14-25 — the Config struct only deserializes cmd, entrypoint, env, working_dir. There is no user field, so serde silently drops it.
src/inject.rs:69-86 — build_exec_script only emits cd, export, and exec /bin/sh -c. There is no su/setpriv/setuid to drop privileges.
src/scripts/slim-init.sh:41-54 — the runtime (slim.cmd) path also execs the command directly as root (PID 1).
src/build.rs:78-80 — only env and working_dir are passed through; user isn't even a parameter.
Proposed implementation
Add a user: Option<String> field to the Config struct in src/inject.rs (serde #[serde(rename_all = "PascalCase")] already maps it to User).
Pass config.user through build_inner into build_exec_script.
In build_exec_script, emit a privilege drop before the final exec. The user field may be a username, a uid, or uid:gid (OCI spec), so handle all forms. su is universally available (BusyBox su included), but setpriv --reuid/--regid is cleaner when present. A portable fallback:
if[ -n "$SLIM_USER"];thenexec su "$SLIM_USER" -c 'exec /bin/sh -c "..."'fi
For the runtime override path (slim-init.sh), apply the same drop so slim run --cmd also respects the configured user.
Acceptance criteria
A Dockerfile with USER <name> results in id reporting that user inside the VM.
Both build-time CMD (/slim/exec) and run-time override (slim.cmd=) run as the configured user.
Supports user, uid, and uid:gid forms per the OCI image spec.
Falls back to root when USER is unset (current behavior).
## Problem
slim currently ignores the `USER` directive from the image config. The VM's init and the container's CMD/ENTRYPOINT always run as **root (uid 0)**, regardless of any `USER` directive in the Dockerfile.
For example, a Dockerfile containing:
```dockerfile
FROM alpine:latest
RUN adduser -D marvin
USER marvin
CMD ["/bin/sh"]
```
still boots with `id` reporting `uid=0(root)` inside the VM.
## Root cause
The OCI image config exposes `.Config.User` (populated by the `USER` Dockerfile directive), but slim never reads it:
- **`src/inject.rs:14-25`** — the `Config` struct only deserializes `cmd`, `entrypoint`, `env`, `working_dir`. There is **no `user` field**, so serde silently drops it.
- **`src/inject.rs:69-86`** — `build_exec_script` only emits `cd`, `export`, and `exec /bin/sh -c`. There is **no `su`/`setpriv`/setuid** to drop privileges.
- **`src/scripts/slim-init.sh:41-54`** — the runtime (`slim.cmd`) path also `exec`s the command directly as root (PID 1).
- **`src/build.rs:78-80`** — only `env` and `working_dir` are passed through; `user` isn't even a parameter.
## Proposed implementation
1. Add a `user: Option<String>` field to the `Config` struct in `src/inject.rs` (serde `#[serde(rename_all = "PascalCase")]` already maps it to `User`).
2. Pass `config.user` through `build_inner` into `build_exec_script`.
3. In `build_exec_script`, emit a privilege drop before the final `exec`. The `user` field may be a username, a uid, or `uid:gid` (OCI spec), so handle all forms. `su` is universally available (BusyBox `su` included), but `setpriv --reuid`/`--regid` is cleaner when present. A portable fallback:
```sh
if [ -n "$SLIM_USER" ]; then
exec su "$SLIM_USER" -c 'exec /bin/sh -c "..."'
fi
```
4. For the runtime override path (`slim-init.sh`), apply the same drop so `slim run --cmd` also respects the configured user.
## Acceptance criteria
- A Dockerfile with `USER <name>` results in `id` reporting that user inside the VM.
- Both build-time CMD (`/slim/exec`) and run-time override (`slim.cmd=`) run as the configured user.
- Supports `user`, `uid`, and `uid:gid` forms per the OCI image spec.
- Falls back to root when `USER` is unset (current behavior).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
slim currently ignores the
USERdirective from the image config. The VM's init and the container's CMD/ENTRYPOINT always run as root (uid 0), regardless of anyUSERdirective in the Dockerfile.For example, a Dockerfile containing:
still boots with
idreportinguid=0(root)inside the VM.Root cause
The OCI image config exposes
.Config.User(populated by theUSERDockerfile directive), but slim never reads it:src/inject.rs:14-25— theConfigstruct only deserializescmd,entrypoint,env,working_dir. There is nouserfield, so serde silently drops it.src/inject.rs:69-86—build_exec_scriptonly emitscd,export, andexec /bin/sh -c. There is nosu/setpriv/setuid to drop privileges.src/scripts/slim-init.sh:41-54— the runtime (slim.cmd) path alsoexecs the command directly as root (PID 1).src/build.rs:78-80— onlyenvandworking_dirare passed through;userisn't even a parameter.Proposed implementation
user: Option<String>field to theConfigstruct insrc/inject.rs(serde#[serde(rename_all = "PascalCase")]already maps it toUser).config.userthroughbuild_innerintobuild_exec_script.build_exec_script, emit a privilege drop before the finalexec. Theuserfield may be a username, a uid, oruid:gid(OCI spec), so handle all forms.suis universally available (BusyBoxsuincluded), butsetpriv --reuid/--regidis cleaner when present. A portable fallback:slim-init.sh), apply the same drop soslim run --cmdalso respects the configured user.Acceptance criteria
USER <name>results inidreporting that user inside the VM./slim/exec) and run-time override (slim.cmd=) run as the configured user.user,uid, anduid:gidforms per the OCI image spec.USERis unset (current behavior).