Skip to content

Instantly share code, notes, and snippets.

@bdougie
Created March 1, 2026 07:12
Show Gist options
  • Select an option

  • Save bdougie/0451c89e671a4d19df28c362638d5695 to your computer and use it in GitHub Desktop.

Select an option

Save bdougie/0451c89e671a4d19df28c362638d5695 to your computer and use it in GitHub Desktop.
RFC: Agent-to-Agent Orchestration via mb CLI — Security Analysis & Implementation Plan

RFC: Agent-to-Agent Orchestration via mb CLI

Status: Draft Author: @bdougie Date: 2026-02-28 Project: masterblaster / StereOS


1. Summary

This RFC proposes enabling agents running inside masterblaster VMs to spawn, monitor, and manage other agent VMs — the "agents deploying agents" pattern. An orchestrator agent, given access to the mb CLI, decomposes large tasks into subtasks, provisions child agents in isolated VMs, monitors their progress, handles failures, and aggregates results.

This document covers the architecture, security threat model, required mitigations, and a phased implementation plan.


2. Motivation

Today, mb manages single-agent sandboxes launched by humans. The interactive demo at agent-orchestrator-demo illustrates a more powerful pattern: a human launches one orchestrator agent, which autonomously spawns a fleet of specialist child agents — each in its own isolated VM with constrained resources, locked-down networking, and readonly source mounts.

This unlocks:

  • Work decomposition: Large tasks (monorepo refactors, multi-service migrations) split across specialist agents
  • Failure isolation: One child crashing doesn't affect siblings or the orchestrator
  • Autonomous recovery: Orchestrator diagnoses failures, rewrites configs, and redeploys without human intervention
  • Resource governance: Each child has explicit CPU/memory/disk budgets

Current State (~60% Implemented)

Capability Status
VM lifecycle (up/down/destroy/ssh/list) Working
jcard.toml config (resources, mounts, secrets, agent) Working
Resource budgets (CPU, memory, disk) Working
Readonly shared mounts Working
Secrets injection via tmpfs Working
Agent harness + restart policy + timeout Working
Egress allowlist (egress_allow) Parsed, not enforced
Agent-accessible mb inside VMs Not implemented
completed agent state Not implemented
Uptime/restart tracking in mb list Not implemented
Parent-child VM relationships Not implemented
Cascading destroy Not implemented

3. Architecture

3.1 Control Plane Bridge

The core problem: agents inside VMs need to call mb commands, but the mb CLI talks to the daemon via a host unix socket (~/.mb/mb.sock) that's inaccessible from inside the guest.

Proposed approach: Vsock API Bridge

┌─────────────────── Host ───────────────────┐
│  mb daemon (unix socket: ~/.mb/mb.sock)    │
│       ▲                                     │
│       │ JSON-RPC                            │
│       ▼                                     │
│  vsock-bridge (per-VM, listens on vsock)   │
│       ▲                                     │
└───────│─────────────────────────────────────┘
        │ vsock
┌───────▼─────────── Guest VM ───────────────┐
│  mb-proxy (translates CLI → vsock RPC)     │
│       ▲                                     │
│       │                                     │
│  agent (calls `mb up`, `mb list`, etc.)    │
└─────────────────────────────────────────────┘
  • vsock-bridge (host-side): Per-VM process/goroutine that accepts vsock connections from the guest and proxies allowed commands to the daemon's unix socket
  • mb-proxy (guest-side): Lightweight binary installed in the mixtape that presents the same mb CLI interface but forwards commands over vsock instead of unix socket
  • Commands are not forwarded raw — the bridge validates and filters them (see Security section)

3.2 Parent-Child Tracking

# Stored in sandbox state (state.json)
{
  "name": "auth-agent",
  "spawned_by": "orchestrator",   # parent sandbox name
  "spawn_depth": 1,               # nesting depth
  "spawn_group": "orchestrator"   # root ancestor
}
  • When a VM calls mb up through the bridge, the bridge injects spawned_by metadata
  • mb list gains a --tree flag to show hierarchy
  • mb destroy --cascade destroys a sandbox and all descendants

3.3 Agent Lifecycle States

Current: created → running → stopped | error

Proposed:

created → running → completed    (agent exited 0)
                  → failed       (agent exhausted restarts)
                  → stopped      (user/parent issued mb down)
                  → error        (VM-level failure)
  • completed: agentd reports exit code 0 → stereosd transitions lifecycle → vsock health reports to host → host updates state
  • failed: agentd reports max_restarts exhausted → same chain
  • Exposed via mb list and mb status

4. Security Analysis

4.1 Threat Model

The orchestration pattern introduces a privilege escalation surface: a sandboxed agent gains the ability to manage host infrastructure. The threats:

Threat Description Severity
T1: Unbounded resource consumption Orchestrator spawns unlimited children, exhausting host CPU/memory/disk High
T2: Lateral movement Agent destroys/SSHs into VMs it didn't spawn (sibling or unrelated sandboxes) High
T3: Privilege escalation via config Agent writes a jcard.toml that grants more privileges than its own (wider egress, writable mounts, more resources) High
T4: Secret exfiltration Agent passes its secrets to child configs, or child configs reference secrets the orchestrator shouldn't distribute Medium
T5: Recursive fork bomb Orchestrator spawns children that spawn grandchildren indefinitely High
T6: Egress bypass Without enforcement, egress_allow is cosmetic — agent can exfiltrate data anywhere Critical
T7: Mount path traversal Agent writes child jcard.toml with host = "/" or host = "~/.ssh" to access sensitive host paths Critical
T8: Denial of service via destroy Compromised agent destroys all VMs on the host High
T9: vsock bridge exploitation Malformed RPC messages to the bridge crash the daemon or execute arbitrary commands Medium

4.2 Required Mitigations

M1: Resource Quotas (addresses T1, T5)

# In orchestrator's jcard.toml
[orchestration]
enabled = true
max_children = 5              # Max direct children
max_depth = 2                 # Max nesting (orchestrator → child → no further)
max_total_cpus = 12           # Total CPU budget across all descendants
max_total_memory = "24GiB"    # Total memory budget across all descendants
max_total_disk = "100GiB"     # Total disk budget across all descendants
  • The vsock bridge enforces these limits before forwarding mb up to the daemon
  • Child [orchestration] sections are always overwritten by the bridge — a child cannot grant itself more orchestration privileges than its parent allows
  • max_depth prevents recursive spawning beyond the configured limit

M2: Scope Isolation (addresses T2, T8)

  • The vsock bridge only allows operations on VMs spawned by the requesting VM
  • mb list inside a VM only shows that VM's children (not all host VMs)
  • mb ssh <name> only works for that VM's children
  • mb destroy <name> only works for that VM's children
  • mb down <name> only works for that VM's children
  • The bridge maps sandbox names to the parent-child graph and rejects out-of-scope requests

M3: Config Privilege Ceiling (addresses T3, T7)

Children cannot exceed their parent's privileges:

  • Egress: Child egress_allow must be a subset of parent's egress_allow
  • Mounts: Child [[shared]] host paths must be within the parent's allowed mount paths. No ../ traversal. No absolute host paths — only paths the parent itself can access.
  • Resources: Child resource requests are checked against the parent's remaining budget
  • Secrets: Children can only receive secrets that the parent explicitly has access to. The bridge validates this.
  • Network mode: Children inherit parent's network mode or more restrictive

The bridge enforces this by intercepting the jcard.toml before forwarding to mb up.

M4: Egress Enforcement (addresses T6)

This is not optional — the demo's security narrative is meaningless without it.

Approach: Guest-side nftables managed by stereosd

# Applied by stereosd at boot, before agentd starts
nft add table inet stereos_egress
nft add chain inet stereos_egress output { type filter hook output priority 0 \; policy drop \; }
nft add rule inet stereos_egress output ct state established,related accept
nft add rule inet stereos_egress output ip daddr 10.0.2.2 accept       # host gateway (for vsock)
nft add rule inet stereos_egress output udp dport 53 accept            # DNS resolution
# For each allowed domain, resolve and add:
nft add rule inet stereos_egress output ip daddr <resolved_ip> accept

Considerations:

  • Domain-based rules require periodic DNS re-resolution (IPs change)
  • Alternative: Use a forward proxy (squid/envoy) on the host with domain-based ACLs, guest routes all traffic through it
  • The proxy approach is more robust for domain-based filtering but adds complexity

M5: Vsock Bridge Hardening (addresses T9)

  • Strict JSON-RPC schema validation — reject malformed messages
  • Rate limiting on the bridge (max N requests/second)
  • Command allowlist: only up, list, status, destroy, down, ssh — no serve, vmhost, pull
  • Request size limits (prevent oversized jcard.toml payloads)
  • Timeout on all bridge operations

M6: Audit Logging

Every command through the vsock bridge is logged:

{
  "timestamp": "2026-02-28T10:15:33Z",
  "source_vm": "orchestrator",
  "command": "up",
  "target": "auth-agent",
  "config_hash": "sha256:abc123...",
  "result": "allowed",
  "reason": ""
}
  • Logged to ~/.mb/audit.log
  • Enables post-hoc review of what any orchestrator did
  • Could feed into ORCHESTRATION_REPORT.md generation

5. Gaps and Implementation Phases

Phase 1: Foundation (Security-Critical)

Item Description Complexity
Egress enforcement nftables rules in stereosd, applied before agentd starts High
--config flag on mb up Accept alternate jcard.toml path Low
completed/failed states Agentd exit → stereosd → vsock → host state machine Medium

Why first: Egress enforcement is a prerequisite for any multi-agent pattern. Without it, the isolation story is broken. The completed state is needed for monitoring.

Phase 2: Orchestration Core

Item Description Complexity
Vsock API bridge Host-side bridge proxying commands from guest to daemon High
mb-proxy guest binary Guest-side CLI that talks to bridge over vsock Medium
Parent-child tracking spawned_by, spawn_depth in sandbox state Medium
[orchestration] config section Resource quotas, max_children, max_depth Medium
Config privilege ceiling Bridge validates child config ≤ parent privileges Medium

Why second: This is the core capability. Requires Phase 1's egress enforcement to be safe.

Phase 3: UX and Monitoring

Item Description Complexity
mb list uptime + restarts Surface agentd metrics over vsock health channel Medium
mb list --tree Hierarchical display of parent/child VMs Low
mb destroy --cascade Destroy VM and all descendants Medium
Audit logging Log all bridge commands to ~/.mb/audit.log Low
Scope isolation Bridge filters list/ssh/destroy to own children only Medium

Phase 4: Hardening

Item Description Complexity
Rate limiting on bridge Prevent DoS via rapid command spam Low
DNS-aware egress (proxy approach) Replace static IP rules with domain-aware proxy High
Bridge schema validation Strict RPC validation, size limits Low
Integration tests End-to-end orchestrator spawning children Medium

6. Open Questions

  1. Should mb inside a VM be opt-in? The [orchestration] section could default to enabled = false, requiring explicit opt-in. This prevents accidental exposure of the vsock bridge.

  2. Proxy vs nftables for egress? nftables is simpler but brittle for domain-based rules (IP changes). A host-side proxy is more robust but adds latency and complexity.

  3. Max nesting depth? The demo shows depth=1 (orchestrator → children). Should we support depth=2+ (children spawning grandchildren)? Recommend starting with max_depth=1 and expanding later.

  4. Secret inheritance model? Should children automatically inherit parent secrets, or require explicit pass-through? Explicit is safer.

  5. What happens when orchestrator is destroyed but children are still running? Options: (a) cascade destroy all children, (b) orphan children and let them finish, (c) configurable behavior.


7. Recommendation

Do not ship the orchestration pattern without egress enforcement and scope isolation. The combination of "agent can spawn VMs" + "no network restrictions" + "no scope boundaries" creates an unacceptable attack surface.

Minimum viable secure orchestration requires:

  1. Enforced egress allowlists (Phase 1)
  2. Scope-isolated bridge (children only) (Phase 2)
  3. Config privilege ceiling (children ≤ parent) (Phase 2)
  4. Resource quotas with max_children/max_depth (Phase 2)

Without all four, an agent that's been prompt-injected or goes off-rails can exhaust host resources, exfiltrate data, or destroy other workloads.


8. References

  • agent-orchestrator-demo/index.html — Interactive demo showcasing the pattern
  • masterblaster/pkg/config/config.go — jcard.toml parsing and validation
  • masterblaster/pkg/daemon/sandbox.go — VM lifecycle state machine
  • masterblaster/pkg/vsock/ — Vsock protocol (health, mounts, secrets, shutdown)
  • masterblaster/cmd/ — CLI command implementations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment