Skip to content

Run gateway sessions as the configured sandbox user - #21

Merged
czpython merged 2 commits into
mainfrom
gateway-session-user
Sep 1, 2026
Merged

Run gateway sessions as the configured sandbox user#21
czpython merged 2 commits into
mainfrom
gateway-session-user

Conversation

@czpython

@czpython czpython commented Sep 1, 2026

Copy link
Copy Markdown
Owner

The gateway opened sessions with sbx exec --interactive <name> bash -l -c <script>, which enters the sandbox as root. The provider already has DOCKER_SBX_SSH_USERNAME (default root), but only the provisioning bootstrap honored it — the gateway path ignored it, so every exec and the SFTP backing shell ran as root.

That breaks agent CLIs, which refuse root: a caller's run died at startup with --dangerously-skip-permissions cannot be used with root/sudo privileges. The template images ship a non-root user for this, and the setting names it; it just never reached the session.

Change

_session_script gains a user. The exec still enters as root in one invocation (no second prep exec, no sbx exec --user, which could not create/chown the home under /home):

  • root (default): the script is byte-identical to before — zero change for default installs.
  • any other user: prepare the per-host home as today, chown it to the user (top level), then exec su -m <user> -s /bin/bash -c <payload>. su -m keeps the exported HOME, so the session home stays /home/<host-name>, now owned by the user who writes it. su runs a PAM session, so /etc/environment (the sandbox env the bootstrap writes) still reaches the session. The user and payload are shlex-quoted.

SbxExecProcess.open reads DockerSbxSettings().ssh_username and passes it through. The SFTP backend calls the same open(), so its backing shell drops to the user too — verified, and covered by a test.

Verification

  • uv run ruff check / ruff format --check / pyright: clean; uv run pytest: 466 pass.
  • test_process.py: the root default is byte-identical; a non-root user gets chown + su with the payload quoted inside; prepare runs before su; the SFTP server command drops to the user; open() honors DOCKER_SBX_SSH_USERNAME from the environment; the PTY path is unchanged.
  • docs/deploy.md: the gateway section states sessions run as DOCKER_SBX_SSH_USERNAME (default root), and that deployments whose agents refuse root set a non-root user present in the template image.

A gateway session entered as root, because `sbx exec` without --user is
root and the gateway path ignored DOCKER_SBX_SSH_USERNAME. Agent CLIs
refuse to run as root, so a caller's run died at startup.

Now one sbx invocation still enters as root to make and own the per-host
home, then drops to DOCKER_SBX_SSH_USERNAME with `su -m`, which keeps the
exported HOME. The root default is byte-identical to before. The SFTP
backing shell goes through the same open(), thus it drops to the user too.
@czpython
czpython merged commit 1b86c09 into main Sep 1, 2026
6 checks passed
@czpython
czpython deleted the gateway-session-user branch September 1, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant