Agentic Covenants

Detect (DE) · Blast radius

Blast radius at the client side layer

deterministic · Outside the model's reasoning

If this concern is breached, how do we know?

What this cell does

bpftrace or Falco userspace catches unsandboxed children, sandbox EPERM events, unexpected network attempts; correlates by session ID.

Artifacts (3)

bubblewrap-with-logging.shview on GitHub
#!/usr/bin/env bash
# ABOUTME: Wraps bubblewrap so its stderr (where EPERM events surface) is teed to syslog tagged agent-sandbox.
# ABOUTME: Replace your agent's bubblewrap invocation with this wrapper; downstream Vector ships the syslog tag to SIEM.

set -euo pipefail

# All args pass through. The wrapper only adds stderr capture.
exec bwrap "$@" 2> >(tee >(logger -t agent-sandbox -p user.warning) >&2)
falco-agent-host.yamlview on GitHub
# ABOUTME: Falco userspace rules for an operator host running agents outside Kubernetes. Detects sandbox escapes and unexpected writes.
# ABOUTME: Pair with json_output: true in falco.yaml so SIEM can parse the events. proc.aname catches multi-level ancestry.
- macro: agent_process
  condition: proc.name in (claude, node, agent-bwrap, mcp-launch)

- macro: agent_ancestor
  condition: proc.aname[0] in (claude, node, agent-bwrap, mcp-launch)
            or proc.aname[1] in (claude, node, agent-bwrap, mcp-launch)
            or proc.aname[2] in (claude, node, agent-bwrap, mcp-launch)

- rule: Agent Process Spawned Outside Sandbox
  desc: A child of an agent process is running outside the agent-sandbox cgroup
  condition: spawned_process and agent_ancestor and not proc.cgroup contains "agent-sandbox"
  output: >
    Unsandboxed child of agent
    (pid=%proc.pid cmd=%proc.cmdline parent=%proc.pname cgroup=%proc.cgroup)
  priority: WARNING
  tags: [agent, sandbox, blast_radius]

- rule: Agent Wrote to Unexpected Path
  desc: Agent process or descendant wrote outside /workspace and tmpfs
  condition: >
    open_write
    and agent_ancestor
    and not fd.name startswith /workspace
    and not fd.name startswith /tmp
    and not fd.name startswith /var/tmp
    and not fd.name startswith /proc
    and not fd.name startswith /dev/null
  output: >
    Agent wrote to unexpected path
    (pid=%proc.pid file=%fd.name parent=%proc.pname)
  priority: WARNING
  tags: [agent, blast_radius]

- rule: Agent Attempted Privilege Escalation
  desc: Agent process or descendant called setuid, setgid, or capset
  condition: >
    evt.type in (setuid, setgid, capset)
    and agent_ancestor
  output: >
    Agent privilege-escalation syscall
    (pid=%proc.pid syscall=%evt.type parent=%proc.pname)
  priority: ERROR
  tags: [agent, sandbox, blast_radius]
network-attempt.btview on GitHub
#!/usr/bin/env bpftrace
// ABOUTME: bpftrace probe that prints agent_network_attempt for connect() syscalls from agent processes.
// ABOUTME: Tune the comm filter for your runtime; "claude" and "node" cover the most common agent process names.

BEGIN {
  printf("agent-sentinel: bpftrace blast-radius probe attached\n");
}

tracepoint:syscalls:sys_enter_connect
/comm == "claude" || comm == "node"/
{
  // Print pid, tgid, comm. Add @pid_to_session map population if you wire
  // the session ID through bubblewrap's --setenv at launch.
  printf("agent_network_attempt pid=%d tgid=%d comm=%s\n",
         pid, tgid, comm);
}

END {
  printf("agent-sentinel: bpftrace blast-radius probe detached\n");
}

Cell notes

Sentinels, Blast radius / Client-side

Control. bpftrace catches unexpected network attempts from the agent process tree. Falco userspace catches unsandboxed children and writes to unexpected paths. bubblewrap stderr captures EPERM (sandbox boundary) events.

Strength. Deterministic for events the kernel surfaces. Failure modes: Falco proc.pname only catches one level (use proc.aname for ancestors); bpftrace requires kernel headers and root; boundary events not correlated with session ID (set SESSION_ID in the bubblewrap launch env).

Tooling

Files in this directory

  • - network-attempt.bt, bpftrace one-liner that prints agent_network_attempt for any connect() syscall from a process tree rooted at the agent. Adjust comm filter for your runtime's actual process names.
  • - falco-agent-host.yaml, Falco userspace rules for unsandboxed agent children and writes outside /workspace//tmp.
  • - bubblewrap-with-logging.sh, wrapper that tees bubblewrap stderr to syslog so EPERM events surface in the SIEM.

Verification


# 1. Falco fires on unsandboxed child
sudo -u agent-runner /usr/local/bin/claude --version &
journalctl -t falco --since "1 minute ago" | grep "Unsandboxed child"

# 2. bpftrace catches network attempt from a sandboxed agent
sudo bpftrace ./network-attempt.bt &
agent-bwrap /tmp -- /bin/sh -c 'curl https://example.com'
# expected: "agent_network_attempt" output

# 3. Boundary EPERM events shipped
journalctl -t agent-sandbox --since "1 minute ago"
# expected: bubblewrap permission denials when triggered

Common mistakes

  • - Falco proc.pname only catches one level. Use proc.aname for ancestors.
  • - bpftrace requires kernel headers and root. Falco userspace is more portable but heavier.
  • - Boundary events not correlated with session ID. Set SESSION_ID in the bubblewrap launch env so events tie back.
  • - Falco rule output not parseable by SIEM. Use json_output: true in falco.yaml.

Citation

NIST CSF 2.0 DE.CM-01, DE.CM-09. NIST SP 800-160 Vol. 1.

Primary failure modes

Documented, not hypothetical. A control whose bypass is undocumented is worse than no control, because somebody trusted it.

  • Falco proc.pname only catches one level (use proc.aname)
  • bpftrace requires kernel headers and root
  • boundary events not correlated with session ID

Crosswalk

NIST CSF 2 0DE.CM-01, DE.CM-09
OTHERNIST SP 800-160 Vol. 1