Skip to main content

Python SDK for Matchlock sandbox

Project description

Matchlock Python SDK

A Python client for Matchlock — a lightweight micro-VM sandbox for running AI-generated code securely with network interception and secret protection.

Requirements

  • Python 3.10+
  • The matchlock CLI binary installed and available on $PATH (or specify its path via Config)

Installation

pip install matchlock

Or install from source:

pip install -e sdk/python

Quick Start

from matchlock import Client, Sandbox

sandbox = Sandbox("python:3.12-alpine")

with Client() as client:
    client.launch(sandbox)

    result = client.exec("echo hello from the sandbox")
    print(result.stdout)  # "hello from the sandbox\n"

Usage

Builder API

The Sandbox class provides a fluent builder for configuring sandboxes:

import os
from matchlock import Client, Sandbox

sandbox = (
    Sandbox("python:3.12-alpine")
    .with_cpus(2)
    .with_memory(512)
    .with_disk_size(2048)
    .with_timeout(300)
    .with_workspace("/home/user/code")
    .allow_host("api.openai.com", "pypi.org")
    .with_network_mtu(1200)
    .block_private_ips()
    .add_secret("API_KEY", os.environ["API_KEY"], "api.openai.com")
)

with Client() as client:
    vm_id = client.launch(sandbox)
    result = client.exec("python3 -c 'print(1+1)'")
    print(result.exit_code)  # 0
    print(result.stdout)     # "2\n"

Streaming Output

Use exec_stream for real-time stdout/stderr streaming:

import sys
from matchlock import Client, Sandbox

with Client() as client:
    client.launch(Sandbox("alpine:latest"))

    result = client.exec_stream(
        "for i in 1 2 3; do echo $i; sleep 1; done",
        stdout=sys.stdout,
        stderr=sys.stderr,
    )
    print(f"Exit code: {result.exit_code}")
    print(f"Duration: {result.duration_ms}ms")

File Operations

Read, write, and list files inside the sandbox:

from matchlock import Client, Sandbox

with Client() as client:
    client.launch(Sandbox("alpine:latest"))

    # Write a file
    client.write_file("/workspace/hello.txt", "Hello, world!")
    client.write_file("/workspace/script.sh", "#!/bin/sh\necho hi", mode=0o755)

    # Read a file
    content = client.read_file("/workspace/hello.txt")
    print(content.decode())  # "Hello, world!"

    # List files
    files = client.list_files("/workspace")
    for f in files:
        print(f"{f.name} ({f.size} bytes, dir={f.is_dir})")

Network Policy & Secrets

Control network access and inject secrets securely:

import os
from matchlock import Client, Sandbox

sandbox = (
    Sandbox("python:3.12-alpine")
    # Only allow these hosts
    .allow_host("api.anthropic.com", "pypi.org", "files.pythonhosted.org")
    # Optional MTU override
    .with_network_mtu(1200)
    # Explicitly block or allow private IPs (10.x, 172.16.x, 192.168.x)
    .with_block_private_ips(True)
    # Inject secret — the MITM proxy replaces the placeholder with the real
    # value only when requests go to the specified host
    .add_secret("ANTHROPIC_API_KEY", os.environ["ANTHROPIC_API_KEY"], "api.anthropic.com")
)

with Client() as client:
    client.launch(sandbox)
    result = client.exec("python3 call_api.py")

Private-IP behavior in the Python SDK:

  • Default (unset): private IPs are blocked whenever a network config is sent.
  • Explicit block: .block_private_ips() or .with_block_private_ips(True).
  • Explicit allow: .allow_private_ips() or .with_block_private_ips(False).
  • Reset to default behavior: .unset_block_private_ips().

If you use CreateOptions(...) directly instead of the builder, set both:

  • block_private_ips_set=True
  • block_private_ips=<True|False>

Filesystem Mounts

Mount host directories or use in-memory/snapshot filesystems:

from matchlock import Client, Sandbox, MountConfig

sandbox = (
    Sandbox("alpine:latest")
    .mount_host_dir("/workspace/src", "/home/user/project/src")
    .mount_host_dir_readonly("/workspace/config", "/home/user/project/config")
    .mount_memory("/workspace/tmp")
    .mount_overlay("/workspace/data", "/home/user/project/data")
    # Or use the generic mount() method:
    .mount("/workspace/custom", MountConfig(type="host_fs", host_path="/tmp/custom"))
)

Custom Configuration

from matchlock import Client, Config

config = Config(
    binary_path="/usr/local/bin/matchlock",
    use_sudo=True,  # Required for TAP devices on Linux
)

with Client(config) as client:
    ...

The binary path can also be set via the MATCHLOCK_BIN environment variable.

Lifecycle Management

from matchlock import Client, Sandbox

client = Client()
client.start()

client.launch(Sandbox("alpine:latest"))
print(client.vm_id)  # e.g., "vm-abc12345"

result = client.exec("echo hello")

# Shut down the sandbox VM
client.close()

# Remove the stopped VM's state directory
client.remove()

Error Handling

from matchlock import Client, Sandbox, MatchlockError, RPCError

with Client() as client:
    try:
        client.launch(Sandbox("alpine:latest"))
        result = client.exec("exit 1")
        if result.exit_code != 0:
            print(f"Command failed: {result.stderr}")
    except RPCError as e:
        print(f"RPC error [{e.code}]: {e.message}")
        if e.is_vm_error():
            print("VM-level failure")
        elif e.is_exec_error():
            print("Execution failure")
        elif e.is_file_error():
            print("File operation failure")
    except MatchlockError as e:
        print(f"Matchlock error: {e}")

API Reference

Sandbox(image: str)

Fluent builder for sandbox configuration.

Method Description
.with_cpus(n) Set number of vCPUs
.with_memory(mb) Set memory in MB
.with_disk_size(mb) Set disk size in MB
.with_timeout(seconds) Set max execution time
.with_workspace(path) Set guest VFS mount point (default: /workspace)
.allow_host(*hosts) Add allowed network hosts (supports wildcards)
.block_private_ips() Block access to private IP ranges
.with_block_private_ips(enabled) Explicitly set private IP blocking true/false
.allow_private_ips() Explicitly allow private IP ranges
.unset_block_private_ips() Reset private IP behavior to SDK default semantics
.with_network_mtu(mtu) Override guest network stack/interface MTU
.add_secret(name, value, *hosts) Inject a secret for specific hosts
.mount(guest_path, config) Add a VFS mount with custom MountConfig
.mount_host_dir(guest, host) Mount a host directory (read-write)
.mount_host_dir_readonly(guest, host) Mount a host directory (read-only)
.mount_memory(guest_path) Mount an in-memory filesystem
.mount_overlay(guest, host) Mount an isolated snapshot of host path
.options() Return the built CreateOptions

Client(config: Config | None = None)

JSON-RPC client for interacting with Matchlock sandboxes. All public methods are thread-safe.

Method Description
.start() Start the matchlock RPC subprocess
.launch(sandbox) Create a VM from a Sandbox builder — returns VM ID
.create(opts) Create a VM from CreateOptions — returns VM ID
.exec(command, working_dir="") Execute a command, returns ExecResult
.exec_stream(command, stdout, stderr, working_dir) Stream command output, returns ExecStreamResult
.write_file(path, content, mode=0o644) Write a file into the sandbox
.read_file(path) Read a file from the sandbox — returns bytes
.list_files(path) List directory contents — returns list[FileInfo]
.close(timeout=0) Shut down the sandbox VM. timeout in seconds; 0 = kill immediately
.remove() Remove the stopped VM's state directory
.vm_id The current VM ID (property)

Types

Type Fields
Config binary_path: str, use_sudo: bool
CreateOptions image, cpus, memory_mb, disk_size_mb, timeout_seconds, allowed_hosts, block_private_ips, block_private_ips_set, mounts, env, vfs_interception, secrets, workspace, dns_servers, network_mtu, image_config
ExecResult exit_code: int, stdout: str, stderr: str, duration_ms: int
ExecStreamResult exit_code: int, duration_ms: int
FileInfo name: str, size: int, mode: int, is_dir: bool
MountConfig type: str, host_path: str, readonly: bool
Secret name: str, value: str, hosts: list[str]
MatchlockError Base exception for all Matchlock errors
RPCError RPC error with code: int and message: str

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matchlock-0.1.21.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

matchlock-0.1.21-py3-none-any.whl (15.8 kB view details)

Uploaded Python 3

File details

Details for the file matchlock-0.1.21.tar.gz.

File metadata

  • Download URL: matchlock-0.1.21.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matchlock-0.1.21.tar.gz
Algorithm Hash digest
SHA256 af0c906858be87fce3ea11ebb6dbf32a62e7a601fda28158d5fa656ced69a2ba
MD5 6ecdd6c478c41e037a5043b9a67cdaf6
BLAKE2b-256 bcbd3a3b5ae09c9da493acfdee549faf05f382b98f4c1aec910ab1b1adff0426

See more details on using hashes here.

Provenance

The following attestation bundles were made for matchlock-0.1.21.tar.gz:

Publisher: python-sdk-release.yml on jingkaihe/matchlock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file matchlock-0.1.21-py3-none-any.whl.

File metadata

  • Download URL: matchlock-0.1.21-py3-none-any.whl
  • Upload date:
  • Size: 15.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for matchlock-0.1.21-py3-none-any.whl
Algorithm Hash digest
SHA256 e42cafafaf5f2dd7f9a6dd51d38324a248f120a1ac693913a0ac6045291f5550
MD5 080f2e6ab2d854359fabed482c1ffc3e
BLAKE2b-256 22070cb19c52d9133eda47db30986be2d309f217bb50bb264069642c3f742fdb

See more details on using hashes here.

Provenance

The following attestation bundles were made for matchlock-0.1.21-py3-none-any.whl:

Publisher: python-sdk-release.yml on jingkaihe/matchlock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page