bubble-sandbox
A Python-specific driver for configuring bubblewrap sandboxes using a specified Python virtual environment, controlling which packages are available.
Each execution runs in a disposable sandbox with the following constraints:
- no network access
- PID isolation
- read-only filesystem (unless host directories are mounted
read-write)
This package provides driver commands:
bubble-sandboxrunsbwrapcommand with arguments which populate the sandbox filesystem using a specified Python virtual environment before running a Python script in the sandbox. The command can optionally copy host-sytem files into the/sandbox/workspacedirectory (the working directory in which the script runs).
Quick Start
Build and run:
uv sync
uv run bubble-sandbox exec-script \
--environment=bare' \
--script='script=print("hello world")' | jq
{
"stdout": "hello world\n",
"stderr": "",
"return_code": 0
}
CLI commands
bubble-sandbox list-environments
List available execution environments and their dependencies.
uv run bubble-sandbox list-environments
──────────────────────────── Available environments ────────────────────────────
- bare
- pandas-only
bubble-sandbox exec-script
Execute a Python script in a sandboxed environment.
Inline script:
uv run bubble-sandbox exec-script \
--environment="bare" \
--script="import sys; print(sys.version_info)"
──────────── Running script: 'import sys; print(sys.version_info)' ─────────────
sys.version_info(major=3, minor=13, micro=12, releaselevel='final', serial=0)
Script stored in a file (same script as above):
uv run bubble-sandbox exec-script \
--environment="bare" \
--script-file=/tmp/foo.py
───────────────────────── Running script: @/tmp/foo.py ─────────────────────────
sys.version_info(major=3, minor=13, micro=12, releaselevel='final', serial=0)
bubble-sandbox exec-command
Execute a shell command in a sandboxed environment.
uv run bubble-sandbox exec-command \
--environment="bare" \
--workdir "/tmp/test" \
"pwd && ls -l"
───────────────────── Running shell command: pwd && ls -l ──────────────────────
/sandbox/work
total 8
-rw-rw-r-- 1 1000 1000 4 Apr 7 16:38 baz.txt
-rw-rw-r-- 1 1000 1000 58 Apr 7 16:38 script.py
bubble-sandbox exec-command
Execute a command line (no shell wrapper) in a sandboxed environment.
$ uv run bubble-sandbox execute -w /tmp/bar/ -e bare -- ls -laF
─────────────────────────── Running command: ls -laF ───────────────────────────
total 12
drwxrwxr-x 2 1000 1000 4096 Apr 7 16:38 ./
drwx------ 4 1000 1000 80 Apr 7 18:11 ../
-rw-rw-r-- 1 1000 1000 4 Apr 7 16:38 baz.txt
-rw-rw-r-- 1 1000 1000 58 Apr 7 16:38 script.py
Note: the -- above prevents the CLI from interpreting the -laf as
one of its own arguments.
Configuration
All settings are configured via environment variables with the BUBBLE_SANDBOX_ prefix:
| Variable | Default | Description |
|---|---|---|
BUBBLE_SANDBOX_ENVIRONMENTS_DIR |
environments |
Path to environments directory |
BUBBLE_SANDBOX_WORKSPACE_DIR |
workspace_data |
Root directory for session workspaces and volumes |
BUBBLE_SANDBOX_MAX_UPLOAD_SIZE_BYTES |
10485760 |
Max total upload size (10 MB) |
BUBBLE_SANDBOX_ALLOWED_EXTENSIONS |
[".txt",".csv",".md",".json",".yaml",".yml",".tsv",".xml"] |
Allowed file extensions (JSON list) |
BUBBLE_SANDBOX_EXECUTION_TIMEOUT_SECONDS |
30 |
Max script execution time |
BUBBLE_SANDBOX_SESSION_IDLE_TIMEOUT_SECONDS |
3600 |
Session idle timeout (seconds) |
BUBBLE_SANDBOX_MAX_SESSIONS |
50 |
Maximum concurrent sessions |
BUBBLE_SANDBOX_ALLOW_PERSISTENT_SESSIONS |
true |
Allow clear_data=false on delete |
BUBBLE_SANDBOX_LOG_LEVEL |
INFO |
Log level (JSON to stdout) |
Adding Environments
Each subdirectory in environments/ is a self-contained Python environment with its own virtual environment and dependencies.
1. Create the environment directory
mkdir environments/my-env
2. Add a pyproject.toml
[project]
name = "my-env"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"requests>=2.32",
"beautifulsoup4>=4.12",
]
3. Sync the environment
cd environments/my-env
uv sync
This creates a .venv/ directory with the declared dependencies installed.
Note: Avoid using a Python here which derives from another virtual environment: instead, use the "base" environment. E.g.:
uv sync --python="/opt/Python-3.13.12"
4. Use it
uv run bubble-sandbox exec-script \
--environment="my-dnv" \
--script='import requests; print(requests.get("http://example.com").status_code)'
Note: network access is disabled in the sandbox by default, so scripts that make HTTP requests will fail. The environment provides the libraries, not network access.
Bundled environments
| Name | Dependencies | Use case |
|---|---|---|
bare |
(none) | Standard library only |
pandas-exec |
pandas 3.0.1+ | Data analysis with pandas |
Sandbox Isolation
Each script execution is wrapped in a bubblewrap sandbox that provides:
- Filesystem isolation: read-only bind mounts for system libraries and the selected venv; a writable tmpfs for
/tmp; uploaded files available in the working directory - User namespace (
--unshare-user): runs as an unprivileged user - PID namespace (
--unshare-pid): cannot see or signal other processes - Network isolation (
--unshare-net): no network access (loopback only) - Session isolation (
--new-session): no TTY control - Auto-cleanup (
--die-with-parent): sandbox is killed if the server process dies
The sandbox working directory and all uploaded files are deleted after execution completes.
Development
# Install dependencies
uv sync
# Sync environment venvs (for local testing) (see note above).
cd environments/bare && uv sync && cd ../..
cd environments/pandas-exec && uv sync && cd ../..
# Run tests (100% coverage required)
uv run pytest
# Lint and format
uv run ruff check
uv run ruff format --check
Metadata
Release files for bubble-sandbox 0.13
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| bubble_sandbox-0.13.tar.gz | 12.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bubble_sandbox-0.13-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.7 kB
Release files / bubble_sandbox-0.13.tar.gz
| Download URL | bubble_sandbox-0.13.tar.gz |
|---|---|
| Size | 12.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
45e6fbb6f23286c3ef8cdf95dc7c34f53169835d1ea7e58742f5ea84f2b3e27d
|
|
BLAKE2b-256 checksum How to use checksums |
81175fc524e2a1dc159b9a7e95ab47e7a7923122cae1c2330b334fa5e20d1fa0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / bubble_sandbox-0.13-py3-none-any.whl
| Download URL | bubble_sandbox-0.13-py3-none-any.whl |
|---|---|
| Size | 14.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
673394b86a8baa8186a6ca69700818ba9d6ffd44ef5748d34191268cd8e08ba5
|
|
BLAKE2b-256 checksum How to use checksums |
b45f498a965ebd05d49e2230db3b405c3a383aad3686085ec30d9918cbcf8778
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for bubble-sandbox 0.13
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.