Matchlock – AI 에이전트 워크로드를 Linux 기반 샌드박스로 보호
Source: Hacker News
Matchlock
Matchlock은 임시 마이크로VM에서 AI 에이전트를 실행하기 위한 CLI 도구입니다. 다음을 제공합니다:
- 네트워크 허용 목록 – 명시적으로 허용된 연결만 허용됩니다.
- MITM 프록시를 통한 비밀 주입 – 비밀이 VM 파일 시스템에 전혀 접근하지 않고 안전하게 주입됩니다.
- 보안 기본값 – 그 외 모든 것(네트워크, 스토리지 등)은 기본적으로 차단됩니다.
비밀이 VM에 들어가지 않으므로 워크로드가 격리되고 안전하게 유지됩니다.
왜 Matchlock인가?
AI 에이전트는 코드를 실행해야 하지만, 기계에 대한 무제한 접근을 허용하는 것은 위험합니다. Matchlock은 전체 Linux 환경을 제공하여:
- 1초 이내 부팅 – 격리되고 일회성이며 기본적으로 잠겨 있습니다.
- 에이전트가 API를 호출할 때 실제 자격 증명을 실시간으로 주입합니다; 샌드박스는 언제나 자리표시자만을 봅니다.
- 기본적으로 네트워크를 차단합니다 – 명시적으로 허용하지 않는 한 샌드박스 밖으로 나갈 수 없습니다.
- 비밀을 보호합니다 – 에이전트가 악성 코드를 실행하도록 속아도 키가 유출되지 않으며, 데이터가 빠져나갈 곳이 없습니다.
샌드박스 내부에서는 에이전트가 완전한 Linux 환경을 이용할 수 있어:
- 패키지 설치
- 파일 작성
- 필요한 모든 임시 작업 수행
외부에서는 호스트 머신이 전혀 손상되지 않습니다. 각 샌드박스는 복사‑쓰기 파일시스템을 사용하며, 작업이 끝나면 사라집니다. Linux 서버든 MacBook이든 동일한 CLI와 동일한 동작을 경험할 수 있습니다.
빠른 시작
시스템 요구 사항
- Linux – KVM 지원 필요
- macOS – Apple Silicon
설치
brew tap jingkaihe/essentials
brew install matchlock
사용법
기본
matchlock run --image alpine:latest cat /etc/os-release
matchlock run --image alpine:latest -it sh
네트워크 허용 목록
matchlock run --image python:3.12-alpine \
--allow-host "api.openai.com" python agent.py
비밀 주입 (VM에 절대 들어가지 않음)
export ANTHROPIC_API_KEY=sk-xxx
matchlock run --image python:3.12-alpine \
--secret ANTHROPIC_API_KEY@api.anthropic.com python call_api.py
장기 실행 샌드박스
# 영구 VM 생성 (VM ID 출력)
matchlock run --image alpine:latest --rm=false
# 기존 VM에 연결
matchlock exec vm-abc12345 -it sh
라이프사이클 명령
matchlock list # 실행 중인 VM 목록
matchlock kill # VM 중지
matchlock rm # VM 삭제
matchlock prune # 중지된 VM 정리
Dockerfile에서 빌드 (BuildKit‑in‑VM 사용)
matchlock build -f Dockerfile -t myapp:latest .
레지스트리 이미지에서 rootfs 사전 빌드 (빠른 시작을 위해 캐시)
matchlock build alpine:latest
이미지 관리
# 모든 이미지 목록
matchlock image ls
# 로컬 이미지 삭제
matchlock image rm myapp:latest
# tarball에서 이미지 가져오기
docker save myapp:latest | \
matchlock image import myapp:latest
Source: …
SDK
Matchlock은 Go와 Python SDK를 제공하여 샌드박스를 애플리케이션에 직접 임베드할 수 있습니다. 프로그래밍 방식으로 VM을 시작하고, 명령을 실행하며, 출력 스트림을 처리하고, 파일을 쓸 수 있습니다.
Go
package main
import (
"fmt"
"os"
"github.com/jingkaihe/matchlock/pkg/sdk"
)
func main() {
// Create a client with the default configuration.
client, _ := sdk.NewClient(sdk.DefaultConfig())
defer client.Close()
// Define the sandbox.
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")
// Launch the sandbox and install curl.
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..."
// Stream a request to Anthropic's API.
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
# Define the 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."}]}'"""
# Use the client to launch the sandbox and run commands.
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)
전체 예제
- Go:
- Python:
Source: …
Architecture
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
다이어그램은 Matchlock CLI, Policy Engine, Transparent Proxy, VFS Server가 호스트 측에 위치하고, Guest Agent, FUSE 워크스페이스, OCI 이미지가 마이크로‑VM(Firecracker 또는 Virtualization.framework) 내부에 존재함을 보여줍니다. 호스트와 VM 간 통신은 vsock 포트 5000과 5001을 통해 이루어집니다.
Network Modes
| 플랫폼 | 모드 | 메커니즘 |
|---|---|---|
| Linux | 투명 프록시 | nftables DNAT on ports 80/443 |
| macOS | NAT (기본값) | Virtualization.framework 내장 NAT |
| macOS | 가로채기 | gVisor userspace TCP/IP at L4 (--allow-host / --secret) |
Docs
전체 개발자 레퍼런스는 **AGENTS.md**에서 확인하세요.
라이선스
MIT