Sandboxed model execution¶
plb sandbox-score runs an untrusted Python inference script inside gVisor's
runsc runtime on a Linux Docker host. This is separate from the trusted
in-process plb score interface.
Operator setup¶
The lab operator must maintain a Linux host, a local Docker Engine at
/var/run/docker.sock, and a reviewed gVisor installation. Follow the official
gVisor installation and
Docker setup guides.
Use a dedicated evaluation host for adversarial submissions. The operator,
Docker daemon, gVisor installation, and runtime image are trusted components.
The submitted script is untrusted.
Review an image containing /usr/bin/env and /usr/local/bin/python, plus any
needed model libraries. Pull or build it explicitly before evaluation, inspect
its contents, and record its immutable local image ID:
docker image inspect your-reviewed-runtime --format '{{.Id}}'
The executor accepts that sha256:... image ID, never a mutable tag, submitted
image, image build instruction, registry URL, or extra Docker flags. Images with
declared volumes are rejected. It does not pull images automatically. Windows,
remote daemons, missing gVisor, and missing resource controllers are rejected;
there is no fallback to ordinary containers or host Python execution.
Script contract¶
The script receives one JSON object on stdin with an ordered features numeric
matrix. Sample IDs, targets, other CSV columns, host paths, credentials, and host
environment variables are not passed. It must print exactly one JSON object:
import json
import sys
rows = json.load(sys.stdin)["features"]
print(json.dumps({"predictions": [sum(row) for row in rows]}))
Return one finite number per row, in input order. Binary classification requires
positive-class probabilities in [0, 1]. Extra fields, duplicate keys, extra log
text on stdout, nonfinite values, and missing predictions are rejected. Stderr is
discarded and shares the output byte cap; untrusted logs never appear in CLI
errors or shareable artifacts.
sha256sum submitted-model.py
plb sandbox-score --model submitted-model.py --model-sha256 MODEL_SHA256 \
--runtime-image sha256:REVIEWED_IMAGE_ID --data local-input.csv \
--feature feature_a --feature feature_b --task-type regression \
--seconds 30 --memory-mb 512 --output outputs/sandbox-predictions.csv
Choose fresh prediction/provenance paths. The selected script is read into a bounded snapshot, verified against its digest, and mounted as one read-only file. It is never imported or deserialized by the host. The current contract supports CPU Python scripts up to 8 MiB, which may embed model parameters. Large multi-file checkpoints, accelerators, participant container images, and remote services are outside this first executor.
Enforced controls¶
Every run requests gVisor, a non-root UID, no Linux capabilities, no new privileges, no network, no IPC sharing, a read-only root filesystem, and only the script mount. Scratch space is a size-limited, non-executable tmpfs. Docker memory/swap/CPU/PID limits and process/file descriptor/file-size limits constrain resource use. A wall-time/output watchdog terminates execution and removes only the uniquely named container created for that run. Cleanup failure is an error.
The default limits are 30 seconds, 512 MiB memory with swap disabled, one CPU,
64 guest processes, 16 MiB scratch space, and 4 MiB combined stdout/stderr. The
host PID cgroup allows 128 additional tasks for gVisor's runtime threads (192
total by default); guest processes are separately limited through RLIMIT_NPROC.
gVisor's resource model
distinguishes guest processes from host runtime tasks. Numeric
input is limited to one million values and 64 MiB of encoded JSON. Public API
callers can choose bounded SandboxLimits; the CLI exposes time and memory.
Dedicated Linux CI installs a checksum-pinned gVisor release and tests real inference, filesystem writes, network denial, host-environment isolation, output flooding, timeouts, memory exhaustion, fork limits, and container cleanup. This is regression evidence, not an independent security audit or proof against all kernel/runtime vulnerabilities.
Keep predictions private¶
The prediction CSV and .sandbox.json provenance are local-only. A malicious
model can encode feature values in valid numeric predictions, errors, timing, or
other observable behavior. Sandboxing restricts host access and direct egress;
it does not make arbitrary model outputs safe to disclose or guarantee absence
of covert channels.
The command never publishes a receipt or returns results to a model submitter.
Evaluate approved local predictions using the normal prediction-table workflow,
then review aggregate disclosure separately. Existing owner_only hidden
benchmark provenance remains restricted to the reviewed trusted scorer; sandbox
results do not silently gain that approval. Never treat an ordinary signed
receipt as remote attestation of this execution environment.