A Python sandboxing tool for enforcing filesystem and network restrictions on arbitrary processes at the OS level
Project description
py-sandboxrt — Python Sandbox Runtime
A Python port of the Anthropic Sandbox Runtime, providing lightweight OS-level sandboxing for arbitrary processes without requiring a container.
py-sandboxrt uses native OS sandboxing primitives (sandbox-exec on macOS, bubblewrap on Linux) and proxy-based network filtering. It can be used to sandbox the behaviour of agents, local MCP servers, bash commands, and arbitrary processes.
Installation
Install from PyPI using pip:
pip install py-sandboxrt
Or using uv:
uv add py-sandboxrt
Development Installation
Clone the repository and install in development mode:
git clone https://github.com/saolalab/py-sandboxrt.git
cd py-sandboxrt
pip install -e ".[dev]"
Or with uv:
uv sync --dev
Quick Start
CLI
# Run a command in the sandbox
srt echo "hello world"
# With debug logging
srt --debug curl https://example.com
# Custom settings file
srt --settings /path/to/srt-settings.json npm install
# Command string mode
srt -c "curl https://example.com && echo done"
Library
import asyncio
from srt import SandboxManager, SandboxRuntimeConfig
from srt.config import NetworkConfig, FilesystemConfig
config = SandboxRuntimeConfig(
network=NetworkConfig(
allowed_domains=["example.com", "api.github.com"],
denied_domains=[],
),
filesystem=FilesystemConfig(
deny_read=["~/.ssh"],
allow_write=[".", "/tmp"],
deny_write=[".env"],
),
)
async def main():
mgr = SandboxManager()
await mgr.initialize(config)
sandboxed_cmd = await mgr.wrap_with_sandbox("curl https://example.com")
import subprocess
proc = subprocess.Popen(sandboxed_cmd, shell=True)
proc.wait()
mgr.cleanup_after_command()
await mgr.reset()
asyncio.run(main())
Configuration
Settings File
By default, py-srt reads ~/.srt-settings.json. Override with --settings:
srt --settings /path/to/config.json <command>
The config file uses the same JSON format as the TypeScript version (camelCase keys are automatically converted):
{
"network": {
"allowedDomains": [
"github.com",
"*.github.com",
"npmjs.org",
"*.npmjs.org"
],
"deniedDomains": ["malicious.com"]
},
"filesystem": {
"denyRead": ["~/.ssh"],
"allowWrite": [".", "src/", "test/", "/tmp"],
"denyWrite": [".env", "config/production.json"]
}
}
Network Configuration (allow-only pattern)
All network access is denied by default.
| Key | Description |
|---|---|
allowedDomains |
Domains permitted to connect to (supports *.example.com wildcards) |
deniedDomains |
Domains explicitly blocked (checked first, overrides allow) |
allowUnixSockets |
macOS only: specific Unix socket paths to allow |
allowAllUnixSockets |
Allow all Unix sockets on both platforms |
allowLocalBinding |
Allow binding to local ports (default: false) |
Filesystem Configuration
| Key | Pattern | Description |
|---|---|---|
denyRead |
deny-only | Paths to block reading (default: allow all reads) |
allowWrite |
allow-only | Paths to allow writing (default: deny all writes) |
denyWrite |
deny-within-allow | Paths to block writing even within allowed paths |
Mandatory Deny Paths (Auto-Protected)
Certain sensitive files are always blocked from writes, even within allowed paths:
- Shell configs:
.bashrc,.bash_profile,.zshrc,.zprofile,.profile - Git configs:
.gitconfig,.gitmodules - Other:
.ripgreprc,.mcp.json - Directories:
.vscode/,.idea/,.claude/commands/,.claude/agents/,.git/hooks/
How It Works
Dual Isolation Model
- macOS: Uses
sandbox-execwith dynamically generated Seatbelt profiles - Linux: Uses
bubblewrapfor containerized filesystem and network namespace isolation
Network Filtering
HTTP and SOCKS5 proxy servers run on the host, filtering all traffic against domain allowlists:
- HTTP/HTTPS — intercepted by an HTTP proxy that validates
CONNECTtunnels and forwards requests - Other TCP — handled by a SOCKS5 proxy for SSH, database connections, etc.
- Linux bridge —
socatrelays between Unix sockets (inside sandbox) and TCP ports (host proxies)
Filesystem Restrictions
- Read (deny-only): All reads allowed by default; deny specific paths
- Write (allow-only): All writes denied by default; explicitly allow paths
- macOS uses Seatbelt regex/glob matching; Linux uses
bubblewrapbind mounts
Architecture
src/srt/
├── __init__.py # Public API exports
├── cli.py # CLI entrypoint (srt command)
├── config.py # Pydantic configuration models
├── sandbox_manager.py # Main orchestrator
├── http_proxy.py # HTTP/HTTPS proxy with domain filtering
├── socks_proxy.py # SOCKS5 proxy with domain filtering
├── macos_sandbox.py # macOS sandbox-exec Seatbelt profiles
├── linux_sandbox.py # Linux bubblewrap sandboxing
├── sandbox_utils.py # Shared utilities (paths, globs, env vars)
├── violation_store.py # In-memory violation tracking
├── platform_utils.py # Platform detection
└── debug.py # Debug logging
Platform Support
| Platform | Mechanism | Dependencies |
|---|---|---|
| macOS | sandbox-exec + Seatbelt profiles |
ripgrep |
| Linux | bubblewrap + network namespaces |
bubblewrap, socat, ripgrep |
| Windows | Not supported | — |
Installing Dependencies
macOS:
brew install ripgrep
Linux (Debian/Ubuntu):
sudo apt-get install bubblewrap socat ripgrep
Debug Logging
Set the SRT_DEBUG environment variable to enable verbose logging to stderr:
SRT_DEBUG=1 srt curl https://example.com
# or
srt --debug curl https://example.com
License
Apache-2.0 — see LICENSE for details.
Credits
Python port of anthropic-experimental/sandbox-runtime.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_sandboxrt-0.1.0.tar.gz.
File metadata
- Download URL: py_sandboxrt-0.1.0.tar.gz
- Upload date:
- Size: 87.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15205e99f0975aff5958de62cbf536fedad1fa546b2a66b3e7bdf4bc2d47ac47
|
|
| MD5 |
5f9cb2c70db46ecb2df205edf711f58d
|
|
| BLAKE2b-256 |
1f5490e069311f326f944d35043be5d502e58f098e8ccadd0a83cd9ae469035f
|
Provenance
The following attestation bundles were made for py_sandboxrt-0.1.0.tar.gz:
Publisher:
publish.yml on saolalab/py-sandboxrt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_sandboxrt-0.1.0.tar.gz -
Subject digest:
15205e99f0975aff5958de62cbf536fedad1fa546b2a66b3e7bdf4bc2d47ac47 - Sigstore transparency entry: 980142350
- Sigstore integration time:
-
Permalink:
saolalab/py-sandboxrt@ca874e9e88687a384afa97c1a3eb7efc44a05a76 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/saolalab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca874e9e88687a384afa97c1a3eb7efc44a05a76 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file py_sandboxrt-0.1.0-py3-none-any.whl.
File metadata
- Download URL: py_sandboxrt-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9695772c11be5341e46955645a75cfc9543393890c519ffcdb879d6e8c364279
|
|
| MD5 |
24efe28d51e6db56cb569f7410fa77c4
|
|
| BLAKE2b-256 |
28b81a1405a97bb98c65ba90aca961800dd6a0b35ede35c2648bec32117a014c
|
Provenance
The following attestation bundles were made for py_sandboxrt-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on saolalab/py-sandboxrt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_sandboxrt-0.1.0-py3-none-any.whl -
Subject digest:
9695772c11be5341e46955645a75cfc9543393890c519ffcdb879d6e8c364279 - Sigstore transparency entry: 980142399
- Sigstore integration time:
-
Permalink:
saolalab/py-sandboxrt@ca874e9e88687a384afa97c1a3eb7efc44a05a76 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/saolalab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca874e9e88687a384afa97c1a3eb7efc44a05a76 -
Trigger Event:
workflow_dispatch
-
Statement type: