Skip to content

Commit 0b79cbc

Browse files
committed
Run safe Pi from a per-user copy of its configuration
Pi 1.4.0 creates lock files beside its settings and credentials, so it cannot start from the root-owned template. The wrapper now copies the template into the zone's state directory on each start. The model key is readable only by the operator. Document why host sudo is left unchanged.
1 parent eab1f16 commit 0b79cbc

3 files changed

Lines changed: 13 additions & 10 deletions

File tree

‎sandbox/srt/README.md‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,11 @@ require an explicit proxy denial, and direct socket checks require a permission
6464
error. Synthetic file contents are checked and deleted. The runtime's own
6565
temporary directory remains writable, as documented upstream.
6666

67-
After **all** shell and Pi checks pass, finish all other root work. Check
68-
`sudo visudo -c`, back up `/etc/sudoers` to `/etc/sudoers.bak-20261028` without
69-
overwriting an existing backup, and use `sudo visudo` to change exactly
70-
`%admin ALL = (ALL) NOPASSWD:ALL` to `%admin ALL = (ALL) ALL`. Leave every included
71-
sudoers file unchanged. Validate again from the same privileged editing session
72-
before closing it, invalidate cached credentials with `sudo -K`, then rerun
73-
the full test with `--after-sudo`. Both host and sandbox `sudo -n true` must fail.
74-
The installer intentionally leaves sudo policy unchanged.
67+
The sandbox itself refuses to execute `sudo` ("Operation not permitted"), so
68+
`safe` does not depend on the host sudo policy. Host sudo stays as it is for
69+
now: the qwen native adapter runs as the operator and calls `sudo -n` for its
70+
admission probe, so removing `NOPASSWD` needs a narrow rule for that probe
71+
first. The installer leaves sudo policy unchanged.
7572

7673
The login-Keychain deny workaround is described in
7774
[srt issue 755](https://github.com/anthropics/sandbox-runtime/issues/755).

‎sandbox/srt/install.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ def template(path):
9191
raise SystemExit("A literal itpcp key is required")
9292
models = json.loads((source / "pi-safe/models.json").read_text())
9393
models["providers"]["itpcp"]["apiKey"] = key
94-
install(zone / "pi-safe/models.json", json.dumps(models, indent=2) + "\n")
94+
install(zone / "pi-safe/models.json", json.dumps(models, indent=2) + "\n", 0o600)
95+
# Only the operator's wrapper may read the key; other local users may not.
96+
os.chown(zone / "pi-safe/models.json", owner.pw_uid, 0)
9597
state = home / ".local/state/pi-safe"
9698
state.mkdir(parents=True, exist_ok=True)
9799
os.chown(state, owner.pw_uid, owner.pw_gid)

‎sandbox/srt/safe‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@ for arg do
1515
done
1616
zone='/Library/Application Support/agent-zones'
1717
agent_home='@HOME@'
18+
state="$agent_home/.local/state/pi-safe"
19+
# Pi writes lock files beside its configuration, so it runs from a copy.
20+
mkdir -p -m 700 "$state/agent"
21+
cp -f "$zone/pi-safe/settings.json" "$zone/pi-safe/mcp.json" "$zone/pi-safe/models.json" "$state/agent/"
1822
cd "$agent_home/Nextcloud"
1923
# Start srt itself without inherited loaders, proxy overrides, or credentials.
2024
exec /usr/bin/env -i \
2125
HOME="$agent_home" USER='@USER@' LOGNAME='@USER@' \
2226
PATH='/opt/agents/srt/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin' \
2327
SHELL=/bin/bash LANG=en_US.UTF-8 TERM="${TERM:-dumb}" MPLBACKEND=Agg \
24-
PI_CODING_AGENT_DIR="$zone/pi-safe" \
28+
PI_CODING_AGENT_DIR="$state/agent" \
2529
PI_CODING_AGENT_SESSION_DIR="$agent_home/.local/state/pi-safe/sessions" \
2630
XDG_CACHE_HOME="$agent_home/.local/state/pi-safe/cache" \
2731
/opt/agents/srt/bin/node \

0 commit comments

Comments
 (0)