火绳枪:基于Linux的AI代理沙箱
Matchlock – Secures AI agent workloads with a Linux-based sandbox

原始链接: https://github.com/jingkaihe/matchlock

## Matchlock:安全的AI代理沙箱 Matchlock 是一款 CLI 工具,旨在通过将 AI 代理隔离在短暂、轻量级的微型虚拟机中来安全地运行它们。它默认优先考虑安全性,通过阻止所有网络访问和防止密钥泄露来实现。密钥通过中间人代理(MITM)在传输过程中注入——虚拟机本身*绝不*会看到您的实际凭据,只会看到占位符。 主要功能包括:快速启动时间(低于一秒)、一个完全隔离的 Linux 环境供代理运行、以及通过允许列表对网络访问进行细粒度控制。沙箱是可丢弃的,使用写时复制文件系统,使用后会消失。 Matchlock 在 Linux(使用 KVM)和 macOS(Apple Silicon)上都能稳定运行,提供统一的体验。它支持从 Dockerfile 构建镜像,使用预构建的 rootfs,并通过类似于 Docker 的命令进行镜像管理。 除了 CLI,Matchlock 还提供 Go 和 Python SDK,用于以编程方式控制沙箱,从而能够将安全性直接嵌入到您的应用程序中。这允许开发人员启动虚拟机、执行命令和流式传输输出——同时为 AI 代理保持安全、隔离的环境。

## Matchlock:保障AI代理工作负载安全 Matchlock (github.com/jingkaihe) 是一个新项目,旨在利用基于Linux的沙箱来保障AI代理工作负载的安全,并通过Apple的虚拟化框架提供macOS支持。它解决了日益增长的代理安全问题,特别是提示注入和数据泄露。 与简单的容器化不同,Matchlock利用Firecracker微型虚拟机(在Linux上)提供硬件级别的隔离。它还具有内置的网络控制——默认拒绝所有流量,仅允许白名单域名——这是防止数据泄露的关键防御措施。用户可以利用现有的Docker/OCI镜像,并且系统可以通过JSON-RPC SDK进行编程。 讨论强调了“软防御”如护栏的局限性,强调需要硬控制。虽然单独的沙箱并不能防止所有攻击,但它可以显著降低损害。讨论中提到了bubblewrap等替代方案,Matchlock提供更强的隔离性和网络控制。还提到了几个类似的项目,包括PacknPlay、Leash和Gondolin。 一个关键的结论是,需要强大的沙箱*和*出站控制,以防止代理泄露敏感数据,即使它们无法直接访问这些数据。创建者承认防止代理利用漏洞的挑战,并强调了分层安全方法的重要性。
相关文章

原文

Matchlock is a CLI tool for running AI agents in ephemeral microVMs - with network allowlisting, secret injection via MITM proxy, and everything else blocked by default. Your secrets never enter the VM.

AI agents need to run code, but giving them unrestricted access to your machine is a risk. Matchlock lets you hand an agent a full Linux environment that boots in under a second - isolated, disposable, and locked down by default.

When your agent calls an API the real credentials are injected in-flight by the host. The sandbox only ever sees a placeholder. The network is sealed by default and nothing gets out unless you say so. Even if the agent is tricked into running something malicious your keys don't leak and there's nowhere for data to go. Inside the agent gets a full Linux environment to do whatever it needs. It can install packages and write files and make a mess. Outside your machine doesn't feel a thing. Every sandbox runs on its own copy-on-write filesystem that vanishes when you're done. Same CLI and same behaviour whether you're on a Linux server or a MacBook.

  • Linux with KVM support
  • macOS on Apple Silicon
brew tap jingkaihe/essentials
brew install matchlock
# Basic
matchlock run --image alpine:latest cat /etc/os-release
matchlock run --image alpine:latest -it sh

# Network allowlist
matchlock run --image python:3.12-alpine \
  --allow-host "api.openai.com" python agent.py

# Secret injection (never enters the VM)
export ANTHROPIC_API_KEY=sk-xxx
matchlock run --image python:3.12-alpine \
  --secret [email protected] python call_api.py

# Long-lived sandboxes
matchlock run --image alpine:latest --rm=false   # prints VM ID
matchlock exec vm-abc12345 -it sh                # attach to it

# Lifecycle
matchlock list | kill | rm | prune

# Build from Dockerfile (uses BuildKit-in-VM)
matchlock build -f Dockerfile -t myapp:latest .

# Pre-build rootfs from registry image (caches for faster startup)
matchlock build alpine:latest

# Image management
matchlock image ls                                           # List all images
matchlock image rm myapp:latest                              # Remove a local image
docker save myapp:latest | matchlock image import myapp:latest  # Import from tarball

Matchlock also ships with Go and Python SDKs for embedding sandboxes directly in your application. Allows you to programmatically launch VMs, exec commands, stream output and write files.

Go

package main

import (
	"fmt"
	"os"

	"github.com/jingkaihe/matchlock/pkg/sdk"
)

func main() {
	client, _ := sdk.NewClient(sdk.DefaultConfig())
	defer client.Close()

	sandbox := sdk.New("alpine:latest").
		AllowHost("dl-cdn.alpinelinux.org", "api.anthropic.com").
		AddSecret("ANTHROPIC_API_KEY", os.Getenv("ANTHROPIC_API_KEY"), "api.anthropic.com")

	client.Launch(sandbox)
	client.Exec("apk add --no-cache curl")

	// The VM only ever sees a placeholder - the real key never enters the sandbox
	result, _ := client.Exec("echo $ANTHROPIC_API_KEY")
	fmt.Print(result.Stdout) // prints "SANDBOX_SECRET_a1b2c3d4..."

	curlCmd := `curl -s --no-buffer https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{"model":"claude-haiku-4-5-20251001","max_tokens":1024,"stream":true,
       "messages":[{"role":"user","content":"Explain TCP to me"}]}'`
	client.ExecStream(curlCmd, os.Stdout, os.Stderr)
}

Python (PyPI)

pip install matchlock
# or
uv add matchlock
import os
import sys

from matchlock import Client, Config, Sandbox

sandbox = (
    Sandbox("alpine:latest")
    .allow_host("dl-cdn.alpinelinux.org", "api.anthropic.com")
    .add_secret(
        "ANTHROPIC_API_KEY", os.environ["ANTHROPIC_API_KEY"], "api.anthropic.com"
    )
)

curl_cmd = """curl -s --no-buffer https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{"model":"claude-haiku-4-5-20251001","max_tokens":1024,"stream":true,
       "messages":[{"role":"user","content":"Explain TCP/IP."}]}'"""

with Client(Config()) as client:
    client.launch(sandbox)
    client.exec("apk add --no-cache curl")
    client.exec_stream(curl_cmd, stdout=sys.stdout, stderr=sys.stderr)

See full examples in examples/go and examples/python.

graph LR
    subgraph Host
        CLI["Matchlock CLI"]
        Policy["Policy Engine"]
        Proxy["Transparent Proxy + TLS MITM"]
        VFS["VFS Server"]

        CLI --> Policy
        CLI --> Proxy
        Policy --> Proxy
    end

    subgraph VM["Micro-VM (Firecracker / Virtualization.framework)"]
        Agent["Guest Agent"]
        FUSE["/workspace (FUSE)"]
        Image["Any OCI Image (Alpine, Ubuntu, etc.)"]

        Agent --- Image
        FUSE --- Image
    end

    Proxy -- "vsock :5000" --> Agent
    VFS -- "vsock :5001" --> FUSE
Loading
Platform Mode Mechanism
Linux Transparent proxy nftables DNAT on ports 80/443
macOS NAT (default) Virtualization.framework built-in NAT
macOS Interception (with --allow-host/--secret) gVisor userspace TCP/IP at L4

See AGENTS.md for the full developer reference.

MIT

联系我们 contact @ memedata.com