-
Notifications
You must be signed in to change notification settings - Fork 24
Open
Milestone
Description
Summary
Apply pod-level and container-level securityContext to all agent pods as part of L1 (Hardened Container) isolation. This restricts process privileges, filesystem access, and syscall surface using standard Kubernetes APIs — no infrastructure changes required.
Target Spec
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65534 # nobody user
fsGroup: 65534
containers:
- name: agent
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefaultWhat Each Field Prevents
| Field | Effect |
|---|---|
runAsNonRoot: true |
Pod fails to start if image uses root — prevents privilege escalation from root inside container |
runAsUser: 65534 |
Forces UID 65534 (nobody) — consistent non-root identity across all agents |
readOnlyRootFilesystem |
Container filesystem is read-only — prevents writing malicious binaries, modifying system files, persisting backdoors |
allowPrivilegeEscalation: false |
Blocks setuid/execve gaining elevated privileges — prevents SUID binary exploits |
capabilities.drop: ["ALL"] |
Removes all Linux capabilities — blocks NET_RAW, SYS_ADMIN, SYS_PTRACE, NET_BIND_SERVICE |
seccompProfile: RuntimeDefault |
Blocks ~50 dangerous syscalls (reboot, mount, ptrace, kexec_load, add_key, etc.) |
Writable Volume Mounts
Since readOnlyRootFilesystem is enabled, agents need explicit emptyDir mounts for writable paths:
spec:
containers:
- name: agent
volumeMounts:
- name: tmp
mountPath: /tmp
- name: agent-workspace
mountPath: /data
- name: pip-cache
mountPath: /home/nobody/.cache
volumes:
- name: tmp
emptyDir:
sizeLimit: "1Gi"
- name: agent-workspace
emptyDir:
sizeLimit: "5Gi"
- name: pip-cache
emptyDir:
sizeLimit: "2Gi"Writable Paths by Agent Framework
| Framework | Required Writable Paths | Reason |
|---|---|---|
| Python (general) | /tmp, /home/nobody/.cache/pip |
Temp files, pip package cache |
| Python + OpenLLMetry | /tmp, /home/nobody/.cache, possibly /home/nobody/.local |
sitecustomize.py bootstrap writes to cache |
| Node.js | /tmp, /home/nobody/.npm, /data/node_modules |
npm cache, module installation |
| Java | /tmp |
Temp files; JAR-based agents rarely need writable fs |
| Go (compiled) | /tmp |
Minimal needs; binary agents are the easiest case |
Note: The
sizeLimiton emptyDir volumes is enforced by kubelet eviction — if the agent exceeds the limit, the pod is evicted. This prevents a compromised agent from filling the node's disk.
Prerequisites
- Agent images must run as non-root. Build pipeline should enforce:
RUN adduser --disabled-password --gecos '' --uid 65534 agent USER agent WORKDIR /data
Implementation Notes
- OpenChoreo controller must preserve (not override) securityContext fields from podTemplate
Acceptance Criteria
- Pod-level and container-level securityContext applied to all new agent pod specs
- Images running as root are rejected with clear error at build time or deployment time
- Agent logs go to stdout (not
/var/log) with read-only rootfs - seccomp RuntimeDefault profile active on all agent pods
- emptyDir volumes mounted for
/tmp,/data, and framework-specific cache paths - emptyDir
sizeLimitenforced — pod evicted if exceeded
Reactions are currently unavailable