Agentic Covenants

Detect (DE) · Blast radius

Blast radius at the server side layer

external · Outside the agent entirely

If this concern is breached, how do we know?

What this cell does

Falco runtime rules for shells in agent containers and writes to sensitive paths; Cilium Hubble drops; ResourceQuota near-limit Prometheus alert; VPC Flow Log REJECTs.

Artifacts (4)

falco-agent-container.yamlview on GitHub
# ABOUTME: Falco runtime rules for agent Pods. Shell spawn, sensitive-path writes, non-allowlisted egress.
# ABOUTME: agent_pod macro matches namespaces matching agent-*; align with the namespace label from controls/identity/server-side/namespace.yaml.
- macro: agent_pod
  condition: k8s.ns.name startswith "agent-"

- list: allowed_agent_egress_ips
  items:
    # Populate from the FQDN allowlist in controls/supply-chain/server-side/cilium-mcp-fqdn-egress.yaml
    # by resolving the names; refresh nightly via a CronJob.
    - "0.0.0.0"   # placeholder; replace

- rule: Agent Container Spawned Shell
  desc: Agent containers should not spawn interactive shells
  condition: >
    spawned_process and agent_pod
    and proc.name in (sh, bash, zsh, fish, dash)
    and proc.tty != 0
  output: >
    Agent pod spawned shell
    (pod=%k8s.pod.name container=%container.name cmd=%proc.cmdline)
  priority: WARNING
  tags: [agent, blast_radius]

- rule: Agent Container Wrote to Sensitive Path
  desc: Agent container writing to /etc, /var/lib, or /usr
  condition: >
    open_write and agent_pod
    and (fd.name startswith /etc
         or fd.name startswith /var/lib
         or fd.name startswith /usr)
  output: >
    Agent pod wrote to sensitive path
    (pod=%k8s.pod.name file=%fd.name)
  priority: ERROR
  tags: [agent, blast_radius]

- rule: Agent Container Outbound to Non-Allowlisted Host
  desc: Agent egress to a host outside the per-agent allowlist
  condition: >
    outbound and agent_pod
    and not fd.sip in (allowed_agent_egress_ips)
  output: >
    Agent pod outbound to non-allowlisted
    (pod=%k8s.pod.name dest=%fd.sip:%fd.sport)
  priority: WARNING
  tags: [agent, blast_radius, supply_chain]

- rule: Agent Container Attempted Privilege Escalation
  desc: Agent container called setuid, setgid, or modified capabilities
  condition: >
    evt.type in (setuid, setgid, capset)
    and agent_pod
  output: >
    Agent privilege-escalation syscall
    (pod=%k8s.pod.name syscall=%evt.type)
  priority: ERROR
  tags: [agent, sandbox, blast_radius]
hubble-export.shview on GitHub
#!/usr/bin/env bash
# ABOUTME: Pipes Hubble flow drops to the SIEM as JSON. Run as a long-running systemd service or DaemonSet sidecar.
# ABOUTME: Without flow export wired up, Hubble is visible only in its own UI and provides no SIEM signal.

set -euo pipefail

SIEM_URL="${SIEM_URL:-https://siem.example.com:9200/agent-sentinel-network/_doc}"
SIEM_TOKEN="${SIEM_TOKEN:?Set SIEM_TOKEN in the environment.}"
NAMESPACE_FILTER="${NAMESPACE_FILTER:-agent-}"

# Stream drops only; allowed flows are too noisy. Add --type policy-verdict
# if you want allow flows for forensic baselining.
hubble observe --type drop --output json --follow --namespace "${NAMESPACE_FILTER}" \
| while IFS= read -r line; do
  curl -sS -X POST "$SIEM_URL" \
    -H "Authorization: Bearer ${SIEM_TOKEN}" \
    -H "Content-Type: application/json" \
    -d "$line" \
    >/dev/null
done
prometheus-quota-alert.yamlview on GitHub
# ABOUTME: Prometheus AlertManager rules firing when an agent namespace hits 85%/95% of its ResourceQuota.
# ABOUTME: Pair with kube-state-metrics; the kube_resourcequota series is what these expressions read.
groups:
- name: agent-namespace-quota
  rules:

  - alert: AgentNamespaceQuotaApproaching
    expr: |
      (kube_resourcequota{namespace=~"agent-.*",resource="requests.cpu",type="used"}
        / kube_resourcequota{namespace=~"agent-.*",resource="requests.cpu",type="hard"}) > 0.85
    for: 5m
    labels:
      severity: warning
      framework: agentic-sentinels
    annotations:
      summary: "Agent namespace {{ $labels.namespace }} CPU quota at >85% for 5m"
      description: |
        Namespace {{ $labels.namespace }} has been consuming over 85% of its
        ResourceQuota.requests.cpu for the last 5 minutes. This is the early
        warning. Either scale capacity or investigate runaway agent.
      runbook: "https://runbooks.example.com/agent-quota-approaching"

  - alert: AgentNamespaceQuotaExceeded
    expr: |
      (kube_resourcequota{namespace=~"agent-.*",resource="requests.cpu",type="used"}
        / kube_resourcequota{namespace=~"agent-.*",resource="requests.cpu",type="hard"}) > 0.95
    for: 1m
    labels:
      severity: critical
      framework: agentic-sentinels
    annotations:
      summary: "Agent namespace {{ $labels.namespace }} CPU quota at >95%"
      description: |
        New Pod admissions in {{ $labels.namespace }} are likely failing.
        Investigate immediately.
      runbook: "https://runbooks.example.com/agent-quota-exceeded"

  - alert: AgentNamespaceMemoryQuotaApproaching
    expr: |
      (kube_resourcequota{namespace=~"agent-.*",resource="requests.memory",type="used"}
        / kube_resourcequota{namespace=~"agent-.*",resource="requests.memory",type="hard"}) > 0.85
    for: 5m
    labels:
      severity: warning
      framework: agentic-sentinels
    annotations:
      summary: "Agent namespace {{ $labels.namespace }} memory quota at >85% for 5m"
vpc-flow-rejects.sqlview on GitHub

501 bytes. Too large to inline; open it on GitHub.

Cell notes

Sentinels, Blast radius / Server-side

Control. Falco runtime detection in agent containers. NetworkPolicy violation events via Cilium Hubble. ResourceQuota near-limit alerts via Prometheus. VPC Flow Logs for unexpected egress.

Strength. Deterministic at the cluster and cloud layer. Failure modes: Falco rules tagged WARNING that should be ERROR (never page anyone); Hubble enabled but flow export not configured (alerts visible only in Hubble UI); ResourceQuota alert at 85% without auto-scale (alerts but no remediation); VPC Flow Log retention too short to see slow exfiltration.

Tooling

  • - Falco 0.40+ deployed as a DaemonSet.
  • - Cilium with Hubble flow export enabled.
  • - Prometheus + AlertManager.
  • - AWS VPC Flow Logs delivered to CloudWatch Logs.

Files in this directory

Verification


# 1. Falco fires on shell spawn in agent Pod
kubectl exec -n agent-claude-prod claude-code -- /bin/sh -i
# expected: Falco alert "Agent pod spawned shell" via journalctl on Falco node

# 2. Hubble surfaces drops
kubectl exec -n agent-claude-prod claude-code -- curl -sS --max-time 3 http://blocked.example.com
hubble observe --pod agent-claude-prod/claude-code --type drop --last 2m
# expected: drop event

# 3. Quota alert fires
# Deploy enough Pods to hit 85% of CPU quota; confirm Prometheus alert.

Common mistakes

  • - Falco rule output not parseable. Use json_output: true in falco.yaml.
  • - Hubble enabled but hubble observe --output json not piped anywhere; SIEM has no detection signal.
  • - ResourceQuota alert at 85% with no auto-scale, alerts but no remediation. Pair with HPA or operator runbook.
  • - VPC Flow Log retention shorter than incident discovery window.

Citation

NIST CSF 2.0 DE.CM-01, DE.CM-09, DE.AE-03. NISTIR 8596 (Cybersecurity for AI).

Primary failure modes

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

  • Falco rules tagged WARNING that should be ERROR
  • Hubble flow export not configured
  • ResourceQuota alert without auto-scale

Crosswalk

NIST CSF 2 0DE.CM-01, DE.CM-09, DE.AE-03
OTHERNISTIR 8596