Agentic Covenants

Recover (RC) · Supply chain

Supply chain at the server side layer

external · Outside the agent entirely

How do I get back to a known-good state and not repeat this?

What this cell does

Rebuild and re-sign images, regenerate SBOMs, rotate signing key if exposed, force redeploy with new SHA pins.

Artifacts (1)

agent-restore-supply-chain-serverview on GitHub
#!/usr/bin/env bash
# ABOUTME: Server-side supply-chain rebuild. Removes emergency denies, optionally rotates signing key, rebuilds + re-signs images, regen SBOMs, force-roll.
# ABOUTME: --rotate-signing-key triggers cosign key rotation; required when the original signing key may have been exposed.

set -euo pipefail

ROTATE_KEY="0"
ARGS=()
for arg in "$@"; do
  case "$arg" in
    --rotate-signing-key) ROTATE_KEY="1" ;;
    *)                    ARGS+=("$arg") ;;
  esac
done
set -- "${ARGS[@]}"

if [[ $# -lt 2 ]]; then
  echo "Usage: agent-restore-supply-chain-server <AGENT_NAME> <INCIDENT_ID> [--rotate-signing-key]" >&2
  exit 64
fi

AGENT_NAME="$1"
INCIDENT_ID="$2"
NAMESPACE="agent-${AGENT_NAME}"

# 1. Remove emergency Kyverno deny ClusterPolicies (image-deny variants and
# emergency-deny-all-agents from the auth row if it lingered).
mapfile -t EMERGENCY < <(
  kubectl get clusterpolicies -o name 2>/dev/null \
    | grep -E "emergency-deny-(image-|all-agents)"
)
for cp in "${EMERGENCY[@]}"; do
  kubectl delete "$cp" 2>/dev/null || true
done

# 2. Remove the emergency Cilium FQDN deny CNP.
kubectl delete cnp -n kube-system emergency-deny-suspect-fqdns 2>/dev/null || true

# 3. Optionally rotate the cosign signing key. Required if the key was on a
# host that may have been compromised. Implementation depends on key store.
if [[ "$ROTATE_KEY" == "1" ]]; then
  if ! command -v cosign >/dev/null 2>&1; then
    echo "REFUSING: cosign not installed; cannot rotate signing key" >&2
    exit 1
  fi
  echo "Rotating cosign signing key. Old signatures must be marked untrusted in Kyverno verifyImages policies."
  # The actual key generation depends on whether you use KMS, file-based, or HSM-backed cosign.
  # cosign generate-key-pair k8s://cosign-system/cosign-key  (Kubernetes)
  # cosign generate-key-pair awskms:///alias/cosign-signer    (AWS KMS)
  # cosign generate-key-pair                                  (file-based, NOT recommended)
  echo "Run the appropriate cosign generate-key-pair command for your key store, then update Kyverno verifyImages policy with the new public key."
fi

# 4. Trigger CI rebuild + re-sign of agent images. Implementation
# environment-specific; this runbook expects a canonical "rebuild" workflow
# you can dispatch.
if command -v gh >/dev/null 2>&1; then
  gh workflow run build-and-sign.yml -f agent="$AGENT_NAME" 2>/dev/null || \
    echo "WARN: failed to dispatch build-and-sign workflow" >&2
fi

# 5. Force redeploy with new SHA pins. The deployment manifest in source
# controls the digest; reapplying picks up the new SHA after CI publishes.
if [[ -d ./manifests/agent ]]; then
  kubectl apply -n "$NAMESPACE" -f "./manifests/agent/${AGENT_NAME}-deployment.yaml" 2>/dev/null || true
  kubectl rollout restart deployment -n "$NAMESPACE" 2>/dev/null || true
fi

logger -t agent-recovery -p user.notice \
  "$(jq -n \
      --arg event "supply_chain_restored_server" \
      --arg agent "$AGENT_NAME" \
      --arg incident "$INCIDENT_ID" \
      --arg rotate "$ROTATE_KEY" \
      --arg actor "$(whoami)" \
      --arg ts "$(date -Iseconds)" \
      '{event:$event, agent:$agent, incident:$incident, rotate_signing_key:$rotate, actor:$actor, ts:$ts}')"

echo "Server-side supply-chain restore complete for $AGENT_NAME"
echo "Recovery is finished. Update Covenants per the lessons learned in this incident."

Cell notes

Restorations, Supply chain / Server-side

Precondition. Interventions L3-C5 has fired (poisoned image deleted from registry, Kyverno deny rule on suspect digest applied, FQDN deny in effect, workloads on last-known-good SHA). All four prior recovery rows complete.

Authority. On-call plus security review.

Tooling

  • - cosign for image re-sign and key rotation.
  • - syft for SBOM regeneration.
  • - crane for registry operations.
  • - KMS or HSM for the new signing key (if rotating).

Files in this directory

  • - agent-restore-supply-chain-server, runbook script. Removes the emergency Kyverno deny ClusterPolicies, optionally rotates the cosign signing key (if --rotate-signing-key is passed), rebuilds and re-signs every agent image, regenerates SBOMs, force-rolls workloads to the new images, removes the emergency Cilium FQDN deny.

Verification


# 1. Emergency Kyverno deny rules removed
kubectl get clusterpolicies | grep -E "emergency-deny-(image-)" || echo "OK: no emergency denies"

# 2. New signed image deploys
kubectl run test --image=ghcr.io/example-org/claude-agent@sha256:NEW_SIGNED_DIGEST -n agent-claude-code-prod
# expected: success

# 3. SBOM attestation present on new image
cosign tree ghcr.io/example-org/claude-agent@sha256:NEW_SIGNED_DIGEST

# 4. Egress to formerly-blocked MCP domain restored (if it was a false-positive)
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://api.anthropic.com -o /dev/null -w "%{http_code}\n"

Common failure modes

  • - Signing key rebuild without rotation when key was exposed. If there's any chance the signing key was on a compromised host, rotate it; rebuild alone keeps the same compromised identity signing.
  • - SBOM diff not used; regeneration alone does not surface what changed. Always diff old vs new SBOM.
  • - Registry-cached compromised images survive on nodes. Force-rollout (covered in the runbook) is mandatory.

Citation

NIST CSF 2.0 RC.RP-01, RC.IM-01; ID.RA-09 (recovery dimension); GV.SC-07 (recovery dimension). NIST SP 800-218 Rev. 1. NIST SP 800-218A. SLSA framework. NIST AI RMF MAP 4.1, MANAGE 3.1.

Primary failure modes

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

  • signing key rebuild without rotation when key was exposed
  • SBOM diff not used; regeneration alone does not surface what changed
  • registry-cached compromised images survive

Crosswalk

NIST CSF 2 0RC.RP-01, RC.IM-01, ID.RA-09, GV.SC-07
NIST AI RMFMAP 4.1, MANAGE 3.1
OWASP AGENTICASI04
OTHERNIST SP 800-218 Rev. 1, NIST SP 800-218A, SLSA framework