Secure AI Agent Deployment
A poorly configured deployment makes every application-level security measure worthless. Four protection layers — image, Kubernetes, CI/CD, network — with ready-to-use configurations.
What is Secure Agent Deployment? Simply Explained
Secure agent deployment is like a multi-layered security system for AI containers: every agent runs in a hardened container without shell and root access. Kubernetes pod security prevents privilege escalation. CI/CD security gates block insecure images. Network policies isolate agents in the network. Without secure deployment, a single compromised container can endanger the entire cluster.
↓ Jump to deployment layers
4 Deployment Security Layers
Every AI agent runs in a hardened, minimal container image. Smaller image = smaller attack surface.
- ▸ Use distroless or alpine base images — no shell, no package manager
- ▸ Run as non-root user (USER 1000:1000) — never UID 0
- ▸ Read-only root filesystem (--read-only) — writes only to explicit tmpfs mounts
- ▸ No SUID/SGID binaries — strip or audit all set-uid files
- ▸ Multi-stage build — dev tools not in production image
# Secure Moltbot agent Dockerfile FROM python:3.12-slim AS builder WORKDIR /build COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt --target /deps FROM gcr.io/distroless/python3-debian12 COPY --from=builder /deps /deps COPY --chown=nonroot:nonroot agent/ /app/ ENV PYTHONPATH=/deps USER nonroot EXPOSE 8080 ENTRYPOINT ["python", "/app/main.py"]
Pod Security Standards and admission controls prevent privilege escalation at the Kubernetes layer.
- ▸ Enforce Restricted Pod Security Standard on agent namespace
- ▸ Set runAsNonRoot: true, runAsUser: 1000 in securityContext
- ▸ readOnlyRootFilesystem: true — mount tmpfs for /tmp only
- ▸ Drop ALL capabilities, add only required (e.g., NET_BIND_SERVICE)
- ▸ No hostNetwork, hostPID, hostIPC access
- ▸ seccompProfile: RuntimeDefault or custom profile
# Kubernetes PodSpec security context for Moltbot agent
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: moltbot-agent
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {medium: Memory, sizeLimit: 256Mi}Block vulnerable or unsigned images before they reach production.
- ▸ Trivy scan in CI — fail pipeline on CRITICAL CVEs
- ▸ OPA policy check — reject images failing security policy
- ▸ Image signing with Sigstore Cosign — verify provenance
- ▸ SBOM generation and attestation on every build
- ▸ Secret scanning (Trufflehog/Gitleaks) on every commit
# GitHub Actions — security gate for Moltbot agent
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: moltbot-agent:${{ github.sha }}
exit-code: '1'
severity: 'CRITICAL,HIGH'
- name: Sign image with Cosign
run: |
cosign sign --yes \
--key env://COSIGN_PRIVATE_KEY \
moltbot-agent:${{ github.sha }}
- name: Generate and attach SBOM
run: |
syft moltbot-agent:${{ github.sha }} -o spdx-json > sbom.json
cosign attest --yes --predicate sbom.json \
--type spdxjson moltbot-agent:${{ github.sha }}AI agents may only communicate with explicitly declared services.
- ▸ Default deny all ingress and egress for agent namespace
- ▸ Allow only: LLM endpoint, declared tool APIs, Moltbot orchestrator
- ▸ Block metadata API access (169.254.169.254) — prevents cloud credential theft
- ▸ Separate network namespace per agent class
- ▸ mTLS between agents via Istio/Cilium
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: moltbot-agent-egress
namespace: moltbot-agents
spec:
podSelector:
matchLabels: {app: moltbot-agent}
policyTypes: [Ingress, Egress]
ingress:
- from:
- podSelector: {matchLabels: {app: moltbot-orchestrator}}
ports: [{port: 8080}]
egress:
- to:
- podSelector: {matchLabels: {app: llm-gateway}}
ports: [{port: 443}]
# Block AWS metadata API explicitly
- to:
- ipBlock:
cidr: 0.0.0.0/0
except: [169.254.169.254/32, 100.100.100.200/32]Frequently Asked Questions
Why should AI agents run in distroless containers?
Distroless containers contain only the application runtime (Python, JVM, etc.) and its dependencies — no shell (/bin/sh), no package manager (apt/apk), no curl, wget, or other utilities. For AI agents this matters: if a prompt injection attack leads to code execution, the attacker has no shell to run commands in, no package manager to install tools, and no common utilities to use as weaponized primitives. The blast radius of a successful exploit is dramatically reduced. The attack goes from 'execute arbitrary commands' to 'can only call Python functions already in the container'.
How does image signing with Sigstore protect AI agent deployments?
Sigstore Cosign creates a cryptographic signature of your container image at build time, stored in a transparency log (Rekor). At deployment time, your admission controller (policy-as-code) verifies: 1) The image was signed by your CI/CD pipeline key. 2) The SBOM attestation matches the image content. 3) The image was scanned clean at build time (scan attestation). This prevents supply chain attacks where an attacker compromises your container registry and replaces a legitimate image with a backdoored one — the compromised image would lack a valid signature.
What resources should AI agents request/limit in Kubernetes?
AI agents have unusual resource profiles: CPU: typically low (agents mostly wait for LLM responses). Memory: can spike if processing large contexts — set limits high enough to avoid OOMKill during normal operation. LLM token budget: limit via Moltbot (not Kubernetes). For typical Moltbot agent: resources: requests: {cpu: '100m', memory: '256Mi'} limits: {cpu: '500m', memory: '512Mi'}. For agents with heavy Python processing: limits: {cpu: '2', memory: '2Gi'}. Always set both requests AND limits — never leave limits unbounded (prevents resource exhaustion).
How do I prevent AI agents from accessing cloud provider metadata APIs?
Cloud providers (AWS, GCP, Azure) expose instance metadata APIs at link-local addresses (AWS: 169.254.169.254, GCP: 169.254.169.254, Azure: 169.254.169.254 or 100.100.100.200). These APIs return instance credentials without authentication — any process inside the VM/pod can call them. A compromised AI agent could exfiltrate cloud credentials via metadata API. Mitigations: 1) NetworkPolicy ipBlock except to block 169.254.169.254/32. 2) IMDSv2 requirement on AWS (requires session token — harder to abuse). 3) Workload Identity (GCP/Azure) instead of node-level credentials.