Skip to content

python: ship nsjail so shimmy's --sandbox works - #2

Merged
m-messer merged 1 commit into
mainfrom
add-nsjail-for-sandbox
Aug 31, 2026
Merged

python: ship nsjail so shimmy's --sandbox works#2
m-messer merged 1 commit into
mainfrom
add-nsjail-for-sandbox

Conversation

@m-messer

Copy link
Copy Markdown
Member

Problem

shimmy provides the --sandbox / SANDBOX_ENABLED feature, which wraps worker processes in nsjail. shimmy's own runtime image builds nsjail from source and ships it at /usr/sbin/nsjail (its image is ubuntu:24.04 specifically "because nsjail requires shared libraries").

This base image's python/Dockerfile does COPY --from=shimmy /shimmy /usr/local/bin/shimmy — it takes only the shimmy binary, not /usr/sbin/nsjail or its runtime libs (libprotobuf, libnl-route-3, libcap2).

Result: any Python evaluation function that sets SANDBOX_ENABLED=true has shimmy fail at startup — NewSandboxedWorkerFactoryos.Stat("/usr/sbin/nsjail") → not found.

Change

  • New nsjail-builder stage, built from python:${PYTHON_VERSION}-slim-${DEBIAN_VERSION} (the same image used at runtime) so the glibc / libstdc++ / libprotobuf ABIs match. Copying nsjail out of shimmy's ubuntu:24.04 image would link it against a newer glibc than bookworm ships. Mirrors shimmy's own nsjail-builder stage; builds nsjail 3.4 (pinned via ARG NSJAIL_VERSION, --recurse-submodules for the vendored kafel).
  • COPY --from=nsjail-builder /nsjail-src/nsjail /usr/sbin/nsjail alongside the existing shimmy copy.
  • Add libcap2 libnl-route-3-200 libprotobuf32 (bookworm package names) to the final apt-get install.
  • RUN ! ldd /usr/sbin/nsjail | grep -q 'not found' — fail the build if a shared lib is missing.

nsjail is dormant unless a function opts into --sandbox, so behaviour is unchanged for every existing consumer. Cost: ~1–2 min build time and ~40–100 MB image size (only when this stage's output is used, i.e. always in the final image — the size increase is unconditional; the runtime behaviour change is not).

Testing

  • build_python.yml matrix (3.9–3.12) builds green on this PR (single-arch amd64).
  • Multi-arch (arm64) build on merge to main — confirm the runtime lib package set resolves on arm64.
  • Smoke: docker run --rm --privileged -e FUNCTION_COMMAND=/bin/sh -e FUNCTION_ARGS="-c,cat /etc/shadow" -e SANDBOX_ENABLED=true -e SANDBOX_RO_BINDS="/usr:/bin:/lib:/lib64" <image> serve exits non-zero (/etc not mounted in the jail).

I could not build this locally (no Docker in the authoring environment) — relying on CI.

Follow-ups (not in this PR)

  • Same nsjail-builder stanza for lean/ (and wolfram/, scratch/) if they should support --sandbox.
  • Downstream: evaluatePython already carries the SANDBOX_* policy env and is waiting on this + a new base tag.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RYbUtnGroazAj1fNjXQmV7

shimmy provides the --sandbox (nsjail) feature and its own runtime image
builds nsjail from source into /usr/sbin/nsjail. This base image copies
only the shimmy binary (`COPY --from=shimmy /shimmy`), not nsjail or its
shared libraries, so any evaluation function that sets SANDBOX_ENABLED=true
has shimmy fail at startup (os.Stat("/usr/sbin/nsjail") -> not found).

Add a nsjail-builder stage that builds nsjail 3.4 from source on the same
python:<ver>-slim-bookworm image used at runtime, so the glibc / libstdc++
/ libprotobuf ABIs match (a binary copied from shimmy's ubuntu:24.04 image
would link against a newer glibc than bookworm provides). Copy the binary
in and install its three runtime libs (libcap2, libnl-route-3-200,
libprotobuf32). A build-time `ldd` check fails the build if a lib is
missing.

nsjail is dormant unless a function opts into --sandbox, so behaviour is
unchanged for every existing image consumer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYbUtnGroazAj1fNjXQmV7
@m-messer
m-messer merged commit a772ef9 into main Aug 31, 2026
4 checks passed
@m-messer
m-messer deleted the add-nsjail-for-sandbox branch August 31, 2026 10:36
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