Skip to content

yujidong/CryptBond

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CryptBond

Cryptographic Access Control for AI Agents

What Does CryptBond Do?

When you ask an AI agent (e.g., through OpenClaw) to "organize my Downloads folder", the agent receives that instruction as an LLM prompt. But nothing prevents the LLM from deciding to read /etc/shadow or delete your home directory.

CryptBond sits between OpenClaw and the LLM API. Before the agent can touch any file, CryptBond checks: "was this operation declared in the user's policy?" If not, it blocks the tool call.

User → OpenClaw → CryptBond Proxy → LLM API
                       ↓
              Blocks unauthorized tool_calls

Key terms:

  • Policy (policy.json) — You declare which directories and operations (read/write/delete) the agent may access
  • Token — A cryptographic signature bound to your policy; the agent cannot forge or modify it
  • Proxy — The HTTP server that intercepts LLM responses and filters unauthorized tool calls
  • FUSE — A Linux filesystem technology that enforces access at the OS kernel level (stronger than proxy, catches bash commands too)

Prerequisites

  • OpenClaw installed and running — verify with curl http://localhost:18789/health
  • An LLM API that OpenClaw is configured to use (Ollama, MiniMax, OpenAI, etc.)
  • Docker deployment: Docker 20+ and Docker Compose V2
  • Manual deployment: Python 3.9+

Not sure which LLM API your OpenClaw uses? Check your OpenClaw config file:

  • On the host: cat ~/.openclaw/openclaw.json
  • In Docker: docker exec openclaw cat /root/.openclaw/openclaw.json

Look for the baseUrl field under providers — that's your LLM API URL.

Verify it works before proceeding:

# For Ollama
curl http://localhost:11434/v1/models
# For OpenAI-compatible APIs (replace URL and key)
curl https://api.example.com/v1/models -H "Authorization: Bearer YOUR_KEY"

Determine Your Setup

Before starting, answer two questions:

1. Where does OpenClaw run? Check with:

docker ps | grep openclaw
  • If you see a running container → OpenClaw is in Docker
  • If nothing shows → OpenClaw is on the host

2. Where will CryptBond run?

  • Docker (recommended) — works the same on all platforms (Windows, Mac, Linux)
  • On the host via pip — requires Python 3.9+

You'll use these answers to pick the right URLs in Step 3 and Step 5 below.

Quick Start

Option A: Docker (Recommended)

Step 1: Clone and enter the Docker directory

git clone https://github.com/yujidong/cryptbond.git
cd cryptbond/docker

Step 2: Create your policy

Copy the example and edit it for your environment:

cp policy.example.json policy.json

Edit policy.json — set resource to the directory the agent should access:

{
    "description": "Agent can read and organize Downloads",
    "resource": "/home/user/Downloads/**",
    "operations": ["read", "write", "delete"],
    "ttl": 300
}

** means "all files and subdirectories recursively". Use * for a single level only.

What path should you use? The resource path must match what the LLM agent actually outputs. To find out:

Agent runs in Paths look like Example resource
Docker container Container paths /root/.openclaw/workspace/**
Linux / WSL2 native Linux paths /home/user/Downloads/**
Docker + WSL2 mount WSL2 mount paths /mnt/c/Users/yourname/Downloads/**

Not sure? Start OpenClaw without CryptBond, give it a task, and observe the file paths in its output. Those exact paths go into resource.

Step 3: Configure the upstream URL

Edit docker-compose.cryptbond.yml — find CRYPTBOND_UPSTREAM and set it to the LLM API URL that your OpenClaw is currently using (see Prerequisites above for how to find it):

environment:
  - CRYPTBOND_UPSTREAM=http://host.docker.internal:11434/v1   # ← change this

See the Upstream URL Reference for common values.

Step 4: Start the proxy

docker compose -f docker-compose.cryptbond.yml up -d

Step 5: Point OpenClaw to CryptBond

Edit your OpenClaw config file (~/.openclaw/openclaw.json on the host, or /root/.openclaw/openclaw.json inside Docker). Find the providers section and change only the baseUrl:

Before:

"your-provider-name": {
    "baseUrl": "http://host.docker.internal:11434/v1",
    "apiKey": "ollama-local"
}

After:

"your-provider-name": {
    "baseUrl": "http://localhost:8001/v1",
    "apiKey": "ollama-local"
}

Replace your-provider-name with the actual name in your config (e.g., ollama-openai). Only baseUrl changes — keep apiKey and other fields unchanged.

The old baseUrl goes into CRYPTBOND_UPSTREAM. The new baseUrl points to CryptBond. Choose the right one for your setup:

Your Setup How to tell New baseUrl
Both in Docker, same compose file Both services in one docker-compose.yml http://cryptbond-proxy:8001/v1
Both in Docker, separate compose files Two separate docker-compose.yml files http://host.docker.internal:8001/v1
OpenClaw in Docker, CryptBond on host docker ps shows OpenClaw but not CryptBond http://host.docker.internal:8001/v1
OpenClaw on host, CryptBond in Docker docker ps shows CryptBond but not OpenClaw http://localhost:8001/v1

Step 6: Verify

curl http://localhost:8001/health   # → {"status": "ok"}
curl http://localhost:8001/audit    # → lists blocked operations

Option B: pip Install

First create policy.json in your working directory (same format as Option A Step 2):

pip install cryptbond[proxy]
cryptbond proxy \
    --config policy.json \
    --upstream http://localhost:11434/v1 \
    --port 8001

--upstream is the LLM API URL your OpenClaw currently uses (the old baseUrl in your OpenClaw config). If you're developing CryptBond itself, use pip install -e ".[proxy]" (editable install from source).

Then configure OpenClaw as in Option A Step 5.

Which method should I use?

Docker Proxy pip Proxy FUSE + Container Python SDK
Choose this if You already use Docker You prefer CLI tools You need maximum security You're building a custom agent
What it blocks LLM tool calls (read/write/delete) LLM tool calls All file access, including bash Only what your code checks
Can agent bypass? No No No Yes (if you forget to check)
Catches bash? No No Yes No
Platform All All Linux only All

Most users should start with Docker Proxy (Option A). It's the simplest to set up and blocks the most common attack vector (LLM tool calls). If you need to prevent the agent from using bash to access files, use FUSE. The Python SDK enforces access only when your code calls block_unauthorized(). If you forget to add that call for a code path, that path is unprotected. The proxy and FUSE enforce automatically regardless of code.

Method 2: FUSE Filesystem Mount (Linux only)

FUSE (Filesystem in Userspace) creates a virtual directory where every file operation is checked at the OS kernel level. This is stronger than the proxy because it catches operations inside bash commands and subprocesses — the proxy only checks tool calls.

Note: FUSE requires a native Linux kernel. It does not work on Windows (including WSL2) or macOS. Windows and Mac users should use the proxy method (Option A or B) instead.

Create policy.json in your working directory (same format as Option A Step 2), then:

pip install -e ".[fuse]"
mkdir -p /mnt/safe
cryptbond mount --config policy.json /mnt/safe --background

Verify the mount is working:

ls /mnt/safe                      # Should list files allowed by policy
cat /mnt/safe/allowed-file.txt    # Should succeed
cat /mnt/safe/../../etc/shadow    # Should fail with permission denied

The agent accesses files through /mnt/safe. Any file outside the policy is blocked by the kernel.

For full protection with OpenClaw in Docker:

docker run -v /mnt/safe:/workspace:ro ghcr.io/openclaw/openclaw:latest

The container's only file access is the FUSE mount — the agent cannot bypass it.

See Configuration Guide for details.

Method 3: Python SDK

For custom Python agents:

from cryptbond.core import Intent
from cryptbond.integrations.openclaw import OpenClawGuard

guard = OpenClawGuard(workspace="/home/user/project", master_key=key)
guard.protect(Intent(prompt="Read files", resource="/home/user/project/**", operation="read"))
guard.block_unauthorized(path, "read")  # raises AccessDeniedError if unauthorized
guard.stop()

Limitations

  • The proxy intercepts LLM tool calls but cannot inspect file operations inside bash commands. For bash protection, use FUSE.
  • Non-file tool calls pass through unaffected.
  • The proxy forces non-streaming mode for reliable filtering. Tokens auto-renew on expiry.
  • When a tool call is blocked, CryptBond replaces it with an error message so the agent sees a clear "access denied" result and can react accordingly.

Troubleshooting

Problem Solution
curl localhost:8001/health fails Check container is running: docker ps. Check logs: docker logs cryptbond-proxy
ERROR: CRYPTBOND_UPSTREAM is required Set the env var in docker-compose.cryptbond.yml
ERROR: Policy file not found Make sure policy.json is in the same directory as the compose file
OpenClaw can't connect to proxy If OpenClaw is in Docker, use http://host.docker.internal:8001/v1 or container name
Agent operations not being blocked Verify policy resource matches the paths the agent uses. Check /audit endpoint
docker compose build fails Make sure you're in the cryptbond/docker/ directory with the correct -f flag

The /audit endpoint (curl http://localhost:8001/audit) returns a JSON log of all blocked operations, including timestamps, paths, and operations attempted. Use it to verify CryptBond is intercepting requests and to debug policy issues.

Documentation

  • Configuration Guide — Docker environment variables, deployment scenarios, upstream URL reference, OpenClaw config examples
  • API Reference — Core, Proxy, SDK, Daemon module documentation
  • Intent Parser — Natural language to intent parsing

Using CryptBond as a Library

from cryptbond.core import Intent, IntentBoundCrypto
import secrets

crypto = IntentBoundCrypto(secrets.token_bytes(32))
session = crypto.establish_session()
token = crypto.sign(
    Intent(prompt="Read downloads", resource="/home/user/Downloads/**", operation="read"),
    session_id=session.session_id, ttl=300,
)

allowed, reason = crypto.verify(token, "/home/user/Downloads/file.txt", "read", session_id=session.session_id)
# allowed == True

allowed, reason = crypto.verify(token, "/etc/shadow", "read", session_id=session.session_id)
# allowed == False

How It Works

User declares intent (resource + operation)
        ↓
CryptBond signs HMAC-SHA256 token bound to intent + session + TTL
        ↓
Agent attempts a file operation
        ↓
CryptBond verifies the operation against the token scope
        ↓
    Within scope → Execute          Outside scope → AccessDeniedError

The token cannot be forged, tampered with, or transferred to another session.

Architecture

cryptbond/
├── core/                    # Cryptographic core (zero dependencies)
├── proxy/                   # HTTP proxy for OpenClaw integration
├── integrations/openclaw/   # OpenClawGuard Python SDK
├── engine/fuse/             # FUSE filesystem enforcement (Linux)
├── daemon/                  # Key isolation daemon
├── docker/                  # Docker deployment files
├── sdk/                     # Python SDK (CryptBondClient)
├── enforce.py               # Token consumer for cryptbond protect
├── cli/                     # Command-line interface
├── docs/                    # Documentation
├── examples/                # Usage examples
└── tests/

Running Tests

pip install -e ".[dev]"
pytest tests/ -v

License

MIT License

About

Cryptographic access control for AI agents — binds HMAC-SHA256 tokens to declared intents, ensuring agents can only perform operations within their authorized scope.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors