Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ jobs:
--security-opt label=disable \
--cap-drop=ALL --cap-add=CHOWN --cap-add=DAC_OVERRIDE \
--cap-add=FOWNER --cap-add=SETUID --cap-add=SETGID --cap-add=KILL \
--pids-limit=4096 \
-e PUID="$(id -u)" -e PGID="$(id -g)" \
-v "$workspace:/workspace" -v "$home_volume:/home/dev" \
"$IMAGE@$DIGEST" sleep infinity
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

### Changed

- Lifecycle adapters and Compose bound the Box to 4096 PIDs
(`--pids-limit=4096` / `pids_limit`), so a runaway Box process cannot
exhaust the host process table.

## v1.2.1 — 2026-07-31

v1.2.0 was built as a draft Candidate but was never published after final
Expand Down
7 changes: 4 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,10 @@ does not contain that server. The upstream Feature enables root login in its
SSHD configuration, but Squarebox publishes no SSH host port or password, and
restricts remote-forwarded listeners to loopback.

Linux capabilities are reduced, but the Box has network access and the host
resources explicitly mounted by its Install identity. Treat code and tools run
inside it as having access to:
Linux capabilities are reduced, and the Box is bounded to 4096 PIDs so a
runaway process cannot exhaust the host's process table. The Box has network
access and the host resources explicitly mounted by its Install identity.
Treat code and tools run inside it as having access to:

- the Workspace, read-write;
- the Managed home, including persisted tool credentials;
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ services:
- SETGID
- KILL

# Fork-bomb insurance: a runaway Box process cannot exhaust host PIDs.
pids_limit: 4096

volumes:
squarebox-home:
# An explicit name keeps lifecycle commands and Compose on the same
Expand Down
2 changes: 1 addition & 1 deletion install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ Add-Seed 'multiplexer' $env:SQUAREBOX_MULTIPLEXERS 'multiplexers'
$RuntimeOptions = @(
'--label', "$ManagedLabel=true", '--label', "$IdentityLabel=$InstallId",
'--cap-drop=ALL', '--cap-add=CHOWN', '--cap-add=DAC_OVERRIDE', '--cap-add=FOWNER',
'--cap-add=SETUID', '--cap-add=SETGID', '--cap-add=KILL',
'--cap-add=SETUID', '--cap-add=SETGID', '--cap-add=KILL', '--pids-limit=4096',
'-e', "PUID=$Puid", '-e', "PGID=$Pgid"
)
$BindSuffix = ''; $ReadOnlyBindSuffix = ':ro'
Expand Down
3 changes: 2 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,8 @@ seed multiplexer "${SQUAREBOX_MULTIPLEXERS:-}" multiplexers
bind_mode=""; ro_bind_mode=ro
RT_OPTS=(--label "$MANAGED_LABEL=true" --label "$IDENTITY_LABEL=$INSTALL_ID"
--cap-drop=ALL --cap-add=CHOWN --cap-add=DAC_OVERRIDE --cap-add=FOWNER
--cap-add=SETUID --cap-add=SETGID --cap-add=KILL -e "PUID=$PUID" -e "PGID=$PGID")
--cap-add=SETUID --cap-add=SETGID --cap-add=KILL --pids-limit=4096
-e "PUID=$PUID" -e "PGID=$PGID")
if [ "$RUNTIME" = podman ]; then
# This development Box mounts a host Workspace, managed configuration,
# system time, and optionally SSH material. A private :Z relabel would make
Expand Down
1 change: 1 addition & 0 deletions tests/test-e2e-evidence.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ grep -Fq '~/.squarebox-compose-e2e' "$WORKFLOW"
grep -Fq '$SQUAREBOX_WORKSPACE/from-compose' "$WORKFLOW"
grep -Fq -- '--cap-drop=ALL --cap-add=CHOWN --cap-add=DAC_OVERRIDE' "$WORKFLOW"
grep -Fq -- '--cap-add=FOWNER --cap-add=SETUID --cap-add=SETGID --cap-add=KILL' "$WORKFLOW"
grep -Fq -- '--pids-limit=4096' "$WORKFLOW"
grep -Fq -- '--userns=keep-id:uid=1000,gid=1000' "$WORKFLOW"
grep -Fq -- '--security-opt label=disable' "$WORKFLOW"
grep -Fq 'podman exec -u dev -e HOME=/home/dev' "$WORKFLOW"
Expand Down
1 change: 1 addition & 0 deletions tests/test-lifecycle-install-state.sh
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ export SQUAREBOX_DIR="$TMP/podman" SQUAREBOX_RUNTIME=podman SQUAREBOX_TAG=v1.1.0
"$ROOT/install.sh" </dev/null
grep -q -- '--security-opt label=disable' "$MOCK_RUNTIME/calls"
grep -q -- '--userns=keep-id:uid=1000,gid=1000' "$MOCK_RUNTIME/calls"
grep -q -- '--pids-limit=4096' "$MOCK_RUNTIME/calls"
! grep -Eq '(^|,|:)Z([,[:space:]]|$)' "$MOCK_RUNTIME/calls"

export MOCK_RUNTIME="$TMP/runtime-podman-bad-id"; mkdir -p "$MOCK_RUNTIME"
Expand Down
1 change: 1 addition & 0 deletions tests/test-lifecycle-powershell.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ $install = [IO.File]::ReadAllText((Join-Path $Root 'install.ps1'))
$uninstall = [IO.File]::ReadAllText((Join-Path $Root 'uninstall.ps1'))
Assert-True ($install.Contains('--userns=keep-id:uid=1000,gid=1000')) 'rootless Podman does not map host identity to dev'
Assert-True ($install.Contains("'--security-opt', 'label=disable'")) 'Podman does not disable private SELinux relabeling'
Assert-True ($install.Contains("'--pids-limit=4096'")) 'installer does not bound Box PID exhaustion'
Assert-True (-not ($install -match ':ro,Z|BindSuffix.*:Z')) 'PowerShell adapter still emits private :Z binds'
Assert-True ($install.Contains('$HomeVolume -cne $State.HOME_VOLUME')) 'Managed-home identity comparison is not case-sensitive'
Assert-True ($install.Contains('$owner.Trim() -cne ''__INSTALL_ID__''')) 'generated adapter case-folds Install identity'
Expand Down