Skip to main content

Secure Docker sandbox container pool for Hermes AI agent — zero-latency sandbox execution

Project description

Hermes Sandbox Setup

Secure Docker sandbox container pool for the Hermes AI agent. Zero-latency sandbox execution with full OWASP Top 10 security coverage.

⚠️ PyPI Publication: This package is ready for PyPI. Pending token setup. See PyPI placeholder section below.


What It Does

Hermes runs directly on the host with full terminal + file access. This means any prompt injection (from web scraping, file reads, or API responses) can execute rm -rf / on your production VM.

This repo provides execution-layer caging — a warm container pool that routes dangerous operations into isolated Docker containers at near-zero latency.

Architecture

┌───────────────────────────────────────┐
│  Hermes Agent (host)                  │
│  - reads your project files           │
│  - thinks about the problem           │
│  - decides: "I need to run a command" │
├───────────────────────────────────────┤
│  Sandbox Pool (3 warm containers)     │
│  ┌───┐ ┌───┐ ┌───┐                   │
│  │ 1 │ │ 2 │ │ 3 │  → docker exec     │
│  └───┘ └───┘ └───┘    (~5ms-160ms)   │
│                                       │
│  If pool empty → cold start           │
│  docker run --rm    (~500-800ms)      │
└───────────────────────────────────────┘

Quick Start

1. Prerequisites

# Docker installed and user in docker group
docker --version
groups | grep docker

# If not: sudo usermod -aG docker $USER && newgrp docker

2. One-Command Setup

bash ~/.hermes/scripts/sandbox-setup.sh --pool-size 3 --memory 128m

Or with all options:

bash ~/.hermes/scripts/sandbox-setup.sh \
  --pool-size 3          \   # warm containers (default: 3)
  --memory 128m          \   # max RAM per container (default: 128m)
  --memory-reserve 16m   \   # soft reservation (default: 16m)
  --cpus 1               \   # CPU cores per container (default: 1)
  --network none         \   # network mode (default: none — for K8s use "host")
  --read-only true       \   # rootfs read-only (default: true)
  --image debian:bookworm-slim \  # container image
  --no-systemd           \   # skip systemd service install

3. Run Commands in Sandbox

# Via warm pool (~5-160ms)
~/.hermes/scripts/sandbox-daemon.sh exec "kubectl get pods"
~/.hermes/scripts/sandbox-daemon.sh exec "curl https://untrusted-site.com"

# Via cold start (~500-800ms, auto fallback)
~/.hermes/scripts/sandbox-exec.sh "pip install some-package"

# Check pool status
~/.hermes/scripts/sandbox-daemon.sh status

4. Systemd Auto-Start

systemctl --user enable --now hermes-sandbox-pool

Security Coverage

OWASP Top 10 (Web) — 9/10 passed

Category Status Implementation
A01 Access Control os.path.realpath() path allowlist, restricted Hermes profiles
A02 Crypto Only MD5 for cache keying (not security-critical)
A03 Injection 16KB command limit + container isolation
A04 Design Zero-Trust WAF documented, defense in depth
A05 Misconfig Resolved absolute paths in config, visudo validation
A06 Components Zero external deps, Debian stable
A07 Auth nginx deny-by-default, listen [IP_ADDRESS]:80
A08 Integrity Hardcoded binary, .deb from git, no `curl
A09 Logging Full audit trail with duration, RC, output lines
A10 SSRF --network none in pool, no HTTP proxies

OWASP Top 10 (LLM) — 1 critical finding fixed

LLM06 — Excessive Agency: Before the audit, Hermes had one profile with full host access. Now:

Profile Toolsets Use Case
default Full access (terminal, file, all) Trusted tasks, known prompts
research web, browser, vision, skills, search, memory, cronjob Web scraping, reading — no RCE risk
sandbox All tools + verbose DEBUG logging Debugging, untrusted terminal
hermes --profile research   # Read-only session
hermes --profile sandbox    # Debug session with audit

See:


Performance

Metric Value
Cold docker run --rm ~521ms
Warm pool exec (avg) ~162-455ms
Pool idle RAM per container ~380-432 KB
Pool idle RAM total (3 containers) ~1.5 MB
Audit log entry size ~100 bytes
Per-container memory limit 128m (configurable)
Per-container CPU limit 1 vCPU

Recovery from failures

Failure Behavior
All containers busy ✅ Transparent cold-start fallback (~600ms)
Docker daemon restart ✅ CID files vanish → cold-start kicks in
Container killed externally ✅ Next call selects different container
Parallel execs on same CID ✅ Atomic mv claim — no race condition
Command > 16KB ✅ Rejected safely (RC=64)

Configuration

sandbox.yaml

pool:
  size: 3
  memory_limit: "128m"
  memory_reserve: "16m"
  cpus: "1"
  network: "none"
  read_only: true
  image: "debian:bookworm-slim"

waf_mode: "read-only"     # drops write/delete/exec at socket layer
allowed_file_paths:
  - "/home/hermes"
tool_overrides: {}

Logging

# In ~/.hermes/config.yaml (per-profile)
logging:
  level: DEBUG         # DEBUG | INFO | WARNING | ERROR
  backup_count: 3
  max_size_mb: 5
  file: sandbox-log.log  # Optional: separate log file per profile

Audit log location: ~/.hermes/logs/sandbox-audit.log

2026-06-08T05:02:59Z POOL HIT=true rc=0 dur=123ms out=2L cid=89a93f85b752 cmd="echo test123 && cat /etc/hostname"
2026-06-08T05:07:08Z REJECTED 20000B cmd="AAAA..."
2026-06-08T05:10:38Z COLD DONE rc=0 dur=600ms out=1L
2026-06-08T05:25:21Z POOL-STOP containers=3

Go Rewrite — Effort Estimate

The sandbox scripts are not worth rewriting in Go. Here's why:

Current state: 7 KB of bash

  • sandbox-daemon.sh: 6,107 bytes
  • sandbox-exec.sh: 1,080 bytes

What Go would (not) buy

Aspect Bash Go Delta
Exec latency ~162ms ~160ms 0% — Docker is the bottleneck
Startup ~5ms ~1ms Negligible
Binary size 7 KB ~6 MB 857x larger
Concurrency Background & + mv atomic claim Native goroutines Cleaner code, same result
Signal handling trap (flaky with bg) os.Signal Better
Error handling $? checks (easy to miss) Native error returns Better
Cross-platform Linux only Linux/macOS/Windows Better
Maintenance (you) Simple bash — any sysadmin can edit Needs Go toolchain Worse
Distribution Copy one .sh file Build for every arch Worse
Auditability Plain text, grep-friendly Compiled binary — needs source Worse

Effort estimate

Level Hours What you get
Minimal (CLI wrapper) 4-6h Same functionality, 300 lines Go, 6 MB binary
Full (with Docker SDK, health checks, structured logging) 12-16h Proper signal handling, JSON logging, channel-based pool
Complete (replacing all bash + Makefile + systemd integration) 20-30h A proper Go daemon with everything above

Verdict

Not recommended for you. The scripts work. They're 7 KB, trivially editable, and the bottleneck is Docker (not bash). A Go rewrite would make maintenance harder for you (Go toolchain, compilation, cross-compilation, CI) for zero user-facing improvement.

Where Go IS worth it

If you want a rewrite, focus on ToolRecall's MCP daemon (the Python multiplexer). That's where concurrency, JSON-RPC routing, and long-running process management matter. The sandbox wrapper is fine as bash.


Files

├── usr/local/bin/
│   ├── sandbox-daemon.sh    # Pool manager (start/stop/exec/status)
│   ├── sandbox-exec.sh      # Single cold exec (legacy)
│   └── hermes-docker-enable # Hardcoded docker group wrapper
├── etc/
│   ├── sandbox.yaml         # Pool configuration template
│   ├── sandbox-audit.log    # Execution audit trail
│   └── sudoers.d/
│       └── hermes-docker    # NOPASSWD rule for group enable
│   ├── systemd/system/
│   │   └── hermes-sandbox-pool.service
│   └── nginx/
│       └── nginx-toolrecall.conf  # MCP proxy (deny-by-default)
├── debian-package/          # .deb build source
│   └── DEBIAN/
│       ├── control
│       └── postinst
├── SECURITY_AUDIT.md        # OWASP Web Top 10
├── SECURITY_AUDIT_LLM.md    # OWASP LLM Top 10
├── LLM06_FIX.md             # Excessive Agency fix docs
├── FINAL_REPORT.md          # Full metrics and post-audit summary
├── Makefile
└── README.md

PyPI

This package will be available on PyPI as:

pip install hermes-sandbox-setup
# or
uv pip install hermes-sandbox-setup

Then:

hermes-sandbox-setup --pool-size 3 --memory 128m

Status: PyPI token pending. Package structure is ready at /home/hermes/hermes-sandbox-setup/. Run git push once the remote is configured.


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

hermes_sandbox_setup-0.0.1.dev0.tar.gz (6.0 kB view details)

Uploaded Source

Built Distribution

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

hermes_sandbox_setup-0.0.1.dev0-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file hermes_sandbox_setup-0.0.1.dev0.tar.gz.

File metadata

  • Download URL: hermes_sandbox_setup-0.0.1.dev0.tar.gz
  • Upload date:
  • Size: 6.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for hermes_sandbox_setup-0.0.1.dev0.tar.gz
Algorithm Hash digest
SHA256 9621998536503de2b4f0647987db233451cd5cf601534e471d03211b39fbaa78
MD5 7e8372fb51dfeecf1957b71b494f8394
BLAKE2b-256 b4b5fdc8f5501a5b551058a23fd0b252efcdc3f65845b2fb1b5491f71eababef

See more details on using hashes here.

File details

Details for the file hermes_sandbox_setup-0.0.1.dev0-py3-none-any.whl.

File metadata

  • Download URL: hermes_sandbox_setup-0.0.1.dev0-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for hermes_sandbox_setup-0.0.1.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 709b895998c17cee965ff1f9c4491de82204234abb3ead7d37649d95969b4920
MD5 b233e8d1ac3db3818be766118b9326ed
BLAKE2b-256 d531c3c567498d2b503c95f5cc207c0a4c4997e9fbc72570ea857bb974e6b7b1

See more details on using hashes here.

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