Respond (RS) · Blast radius
Blast radius at the server side layer
external · Outside the agent entirely
How do I stop the bleeding now?
What this cell does
Apply emergency NetworkPolicy default-deny, scale Deployment to zero, force-delete pods, optionally cordon node, block egress at cloud firewall.
Artifacts (3)
agent-contain-serverview on GitHub#!/usr/bin/env bash
# ABOUTME: Server-side blast-radius containment runbook. NetworkPolicy default-deny, scale to zero, force-delete pods.
# ABOUTME: Pre-stage networkpolicy-emergency-deny.yaml and sg-deny-all-egress.json under /etc/agents/emergency/.
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: agent-contain-server <AGENT_NAME>" >&2
exit 64
fi
AGENT_NAME="$1"
NAMESPACE="agent-${AGENT_NAME}"
INCIDENT_ID="$(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')"
EMERGENCY_DIR="${EMERGENCY_DIR:-/etc/agents/emergency}"
DRAIN_NODES="${DRAIN_NODES:-0}" # set to 1 to cordon and drain nodes hosting the agent
BLOCK_EGRESS_SG="${BLOCK_EGRESS_SG:-1}"
if [[ ! -r "$EMERGENCY_DIR/networkpolicy-emergency-deny.yaml" ]]; then
echo "REFUSING: $EMERGENCY_DIR/networkpolicy-emergency-deny.yaml not pre-staged" >&2
exit 1
fi
# 1. Apply emergency NetworkPolicy default-deny in the agent's namespace.
kubectl apply -n "$NAMESPACE" -f "$EMERGENCY_DIR/networkpolicy-emergency-deny.yaml"
# 2. Scale all Deployments in the agent namespace to zero.
kubectl scale deployment -n "$NAMESPACE" --all --replicas=0 2>/dev/null || true
# 3. Force-delete pods that did not respect scale-down.
kubectl delete pods -n "$NAMESPACE" --all --force --grace-period=0 2>/dev/null &
DELETE_PID=$!
# 4. Optional: cordon and drain the nodes hosting the agent if compromise
# extends to the host (Falco events from outside the namespace, kernel-level
# escape suspected, etc.).
if [[ "$DRAIN_NODES" == "1" ]]; then
mapfile -t AGENT_NODES < <(
kubectl get pods -n "$NAMESPACE" -o jsonpath='{.items[*].spec.nodeName}' 2>/dev/null \
| tr ' ' '\n' | sort -u
)
for node in "${AGENT_NODES[@]}"; do
[[ -z "$node" ]] && continue
kubectl cordon "$node" 2>/dev/null || true
kubectl drain "$node" \
--grace-period=0 --force \
--delete-emptydir-data --ignore-daemonsets &
done
fi
# 5. Block egress at cloud firewall (AWS Security Group example).
if [[ "$BLOCK_EGRESS_SG" == "1" ]] && command -v aws >/dev/null 2>&1; then
SG_ID="$(aws ec2 describe-security-groups \
--filters "Name=tag:agent,Values=$AGENT_NAME" \
--query 'SecurityGroups[0].GroupId' --output text 2>/dev/null || true)"
if [[ -n "$SG_ID" && "$SG_ID" != "None" ]]; then
aws ec2 update-security-group-rule-descriptions-egress \
--group-id "$SG_ID" \
--ip-permissions "$(cat "$EMERGENCY_DIR/sg-deny-all-egress.json")" \
2>/dev/null || echo "WARN: SG rule update failed; SG may be referenced elsewhere" >&2
fi
fi
wait
logger -t agent-incident -p user.warning \
"$(jq -n \
--arg event "blast_radius_contained_server" \
--arg agent "$AGENT_NAME" \
--arg incident "$INCIDENT_ID" \
--arg actor "$(whoami)" \
--arg ts "$(date -Iseconds)" \
'{event:$event, agent:$agent, incident:$incident, actor:$actor, ts:$ts}')"
echo "Server-side blast radius contained for $AGENT_NAME (incident $INCIDENT_ID)"
networkpolicy-emergency-deny.yamlview on GitHub# ABOUTME: Emergency default-deny NetworkPolicy applied during blast-radius containment. No allow rules; ingress and egress fully denied.
# ABOUTME: Pre-stage at /etc/agents/emergency/. CNI-dependent — verify your CNI enforces NetworkPolicy at all (some legacy setups do not).
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: emergency-deny-everything
annotations:
incident: "true"
spec:
podSelector: {} # all pods in the namespace
policyTypes:
- Ingress
- Egress
# No ingress or egress rules below = deny everything.
sg-deny-all-egress.jsonview on GitHub[
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0",
"Description": "Emergency lockdown: incident response. Egress denied."
}
]
}
]
Cell notes
Interventions, Blast radius / Server-side
Trigger. Falco alert from cluster, NetworkPolicy violation spike, ResourceQuota near-limit emergency, cross-namespace operations from an agent SA.
Authority. On-call, no second approval.
Speed target. Under 5 seconds for namespace freeze, under 60 seconds for full drain.
Tooling
- -
kubectlwith permission to apply NetworkPolicies, scale Deployments, and (for cordon-and-drain) cordon nodes. - - AWS CLI (or GCP/Azure equivalent) with permission to update Security Group egress rules.
Files in this directory
- -
agent-contain-server, runbook script. Applies emergency NetworkPolicy default-deny, scales agent Deployments to zero, force-deletes pods, optionally cordons and drains nodes, and blocks egress at the cloud firewall. - -
networkpolicy-emergency-deny.yaml, pre-staged default-deny NetworkPolicy with no allow rules. Applied to the agent namespace. Pre-stage at/etc/agents/emergency/networkpolicy-emergency-deny.yaml. - -
sg-deny-all-egress.json, pre-staged AWS Security Group egress-rule descriptions used by the runbook to update the agent's SG. Pre-stage at/etc/agents/emergency/sg-deny-all-egress.json.
Verification
# 1. NetworkPolicy in effect
kubectl get networkpolicy -n agent-claude-code-prod emergency-deny-everything
# 2. Egress blocked
kubectl exec -n agent-claude-code-prod $(kubectl get pods -n agent-claude-code-prod -o name | head -1) -- \
curl -sS --max-time 3 https://example.com 2>&1 || echo "OK: egress blocked"
# 3. Deployment scaled to zero
kubectl get deployments -n agent-claude-code-prod -o jsonpath='{.items[*].spec.replicas}'
# expected: 0 0 0...
# 4. No pods running
kubectl get pods -n agent-claude-code-prod
# expected: empty
Common mistakes
- -
kubectl drainwithout--grace-period=0honorsterminationGracePeriodSeconds: 300, the pod runs for 5 minutes. Use--force --grace-period=0. - - Existing TCP connections survive NetworkPolicy changes (CNI-dependent). Verify by attempting a fresh connection after applying.
- - Cordoning the wrong node, verify the pods' actual node placement before draining.
- - Cloud firewall rule modification fails silently if the security group is referenced by other resources. Verify rule before declaring contained.
Citation
NIST CSF 2.0 RS.MI-01, RS.MI-02; PR.IR-01 (response dimension). NIST SP 800-61 Rev. 2. NISTIR 8596. OWASP ASI05, ASI08. NIST AI RMF MANAGE 4.1.
Primary failure modes
Documented, not hypothetical. A control whose bypass is undocumented is worse than no control, because somebody trusted it.
- drain without --grace-period=0 honors 5-min terminationGracePeriodSeconds
- existing TCP connections survive NetworkPolicy changes (CNI-dependent)
- cloud SG modification fails silently if SG is referenced elsewhere
Crosswalk
| NIST CSF 2 0 | RS.MI-01, RS.MI-02, PR.IR-01 |
|---|---|
| NIST AI RMF | MANAGE 4.1 |
| OWASP AGENTIC | ASI05, ASI08 |
| OTHER | NIST SP 800-61 Rev. 2, NISTIR 8596 |
Cite this cell:
https://agenticcovenants.com/respond/blast-radius/server-side/