The Seccomp Profile Is Set To RuntimeDefault In Pod
More Info:
The RuntimeDefault seccomp profile restricts the syscalls a container may make, reducing the kernel attack surface. Pods should set this profile in their security context.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS GKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List pods missing RuntimeDefault seccomp
- Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o json | \jq -r '.items[]| select((.metadata.annotations."seccomp.security.alpha.kubernetes.io/pod" // "") != "runtime/default"and (.spec.securityContext.seccompProfile.type // "") != "RuntimeDefault")| {namespace: .metadata.namespace, name: .metadata.name,podSeccomp: .spec.securityContext.seccompProfile.type,podAnnotation: .metadata.annotations."seccomp.security.alpha.kubernetes.io/pod"}' -
Review pod/containers for compatibility with RuntimeDefault
- For each listed pod, inspect its spec and containers for special syscall or privileged needs (e.g., hostPath mounts, privileged containers, CAP_SYS_ADMIN, low‑level networking/storage agents):
# Example for one podkubectl -n <NAMESPACE> get pod <POD_NAME> -o yaml- Coordinate with the application owner to confirm whether the workload can run under the restricted RuntimeDefault profile, or whether it truly needs a custom seccomp profile or privileged capabilities.
-
Decide the policy per workload
- For each pod type (usually via its controller: Deployment, DaemonSet, StatefulSet, Job, CronJob):
- Preferred: enforce
RuntimeDefaultat pod level. - If incompatible: document the justification, consider designing and referencing a specific seccomp profile instead of leaving it unset or fully unconfined.
- Preferred: enforce
- For each pod type (usually via its controller: Deployment, DaemonSet, StatefulSet, Job, CronJob):
-
Update controller manifests to set RuntimeDefault
- Identify the owning controller:
kubectl -n <NAMESPACE> get pod <POD_NAME> -o jsonpath='{.metadata.ownerReferences}'- Edit the controller spec to add a pod-level
securityContextwithseccompProfileset toRuntimeDefault(or update existing):
kubectl -n <NAMESPACE> edit deployment <DEPLOYMENT_NAME>- In the
spec.template.specsection, ensure:
securityContext:seccompProfile:type: RuntimeDefault- If pod-level is not possible and you accept that risk, set it at container level for each container instead:
containers:- name: <CONTAINER_NAME>securityContext:seccompProfile:type: RuntimeDefault- Remove deprecated pod annotation
seccomp.security.alpha.kubernetes.io/podwhere present onceseccompProfileis set.
-
Apply changes via manifests/IaC when applicable
- If resources are managed by GitOps/IaC, modify the source manifests or Helm charts rather than using
kubectl edit, mirroring the samesecurityContext.seccompProfile.type: RuntimeDefaultstructure, then redeploy through your standard pipeline to avoid drift.
- If resources are managed by GitOps/IaC, modify the source manifests or Helm charts rather than using
-
Verify pods now use RuntimeDefault
- After controllers roll out updated pods, re-run the audit, and confirm previously flagged pods now appear with
RuntimeDefault(or a justified exception list):
kubectl get pods --all-namespaces -o json | \jq -r '.items[]| select(.metadata.annotations."seccomp.security.alpha.kubernetes.io/pod" == "runtime/default"or .spec.securityContext.seccompProfile.type == "RuntimeDefault")| {namespace: .metadata.namespace, name: .metadata.name,seccompProfile: .spec.securityContext.seccompProfile.type}' - After controllers roll out updated pods, re-run the audit, and confirm previously flagged pods now appear with
Using kubectl
# 1. List all pods and show their seccomp profile status (cluster-wide)
# Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
namespace: .metadata.namespace,
name: .metadata.name,
podAnnotation: .metadata.annotations["seccomp.security.alpha.kubernetes.io/pod"],
podProfile: .spec.securityContext.seccompProfile.type,
containerProfiles: (
.spec.containers[]
| {name: .name, profile: .securityContext.seccompProfile.type}
)
}'
# Interpretation:
# - Good:
# - podProfile is "RuntimeDefault", OR
# - podAnnotation is "runtime/default", OR
# - every containerProfiles[].profile is "RuntimeDefault"
# - Needs attention:
# - podProfile is null/empty AND podAnnotation is null/empty AND
# one or more containers have profile null/empty
# - Any profile set to "Unconfined"
# 2. Quickly list only pods with missing or unconfined seccomp profiles
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| select(
(
(.spec.securityContext.seccompProfile.type // "") == ""
and (.metadata.annotations["seccomp.security.alpha.kubernetes.io/pod"] // "") == ""
and ([.spec.containers[]
| .securityContext.seccompProfile.type // ""
] | any(. == ""))
)
or
(
(
.spec.securityContext.seccompProfile.type == "Unconfined"
or .metadata.annotations["seccomp.security.alpha.kubernetes.io/pod"] == "unconfined"
or ([.spec.containers[]
| .securityContext.seccompProfile.type // ""
] | any(. == "Unconfined"))
)
)
)
| "\(.metadata.namespace) \t \(.metadata.name)"'
# Interpretation:
# - Every line in the output is a pod that should be manually reviewed.
# - If nothing is printed, all pods have some seccomp configuration and none
# are explicitly Unconfined (you may still choose to tighten policies).
# 3. Inspect a specific pod in detail (replace values as needed)
NAMESPACE=kube-system
POD_NAME=metrics-server-v0.7.0-dbcc8ddf6-gz7d4
kubectl get pod "$POD_NAME" -n "$NAMESPACE" -o yaml \
| yq '.metadata.annotations, .spec.securityContext.seccompProfile, .spec.containers[].securityContext.seccompProfile'
# Interpretation:
# - Confirm whether:
# - metadata.annotations["seccomp.security.alpha.kubernetes.io/pod"] == "runtime/default"
# OR
# - spec.securityContext.seccompProfile.type == "RuntimeDefault"
# OR
# - each container has securityContext.seccompProfile.type == "RuntimeDefault".
# - If none of these are true, this pod is not using RuntimeDefault and
# should be evaluated for updating its pod or container securityContext.
</Accordion>
<Accordion title='Automation'>
```bash
#!/usr/bin/env bash
# Report pods that do NOT use seccomp RuntimeDefault at pod or container level
set -euo pipefail
# REQUIREMENT: run on any machine with kubectl access and jq installed
echo "Scanning pods for non-RuntimeDefault seccomp usage..."
kubectl get pods --all-namespaces -o json | jq -r '
.items[]
| \{
ns: .metadata.namespace,
name: .metadata.name,
pod_anno: .metadata.annotations["seccomp.security.alpha.kubernetes.io/pod"],
pod_type: .spec.securityContext.seccompProfile.type,
containers: (
(.spec.containers // []) as $cs
| [ $cs[]
| {
name: .name,
anno: .securityContext?.seccompProfile?.type,
old_anno: .annotations["seccomp.security.alpha.kubernetes.io/container"]
\}
]
)
}
# Keep only pods where *any* level is NOT RuntimeDefault (or is unset)
| select(
# pod-level modern type not RuntimeDefault or missing
((.pod_type // "") != "RuntimeDefault")
or
# legacy pod annotation not runtime/default or missing
((.pod_anno // "") != "runtime/default")
or
# any container without RuntimeDefault (modern) AND without legacy annotation
([
.containers[]
| (
((.anno // "") != "RuntimeDefault")
and
((.old_anno // "") != "runtime/default")
)
] | any)
)
| "NAMESPACE=\(.ns)\tPOD=\(.name)\tPOD_SEC_PROFILE=\(.pod_type // "NONE")\tPOD_OLD_ANNOT=\(.pod_anno // "NONE")"
'
echo
echo "Explanation:"
echo "- Any line in the output represents a POD that is NOT fully configured with seccomp RuntimeDefault."
echo "- POD_SEC_PROFILE=RuntimeDefault or POD_OLD_ANNOT=runtime/default at the pod level is the modern/legacy compliant setting."
echo "- If the script prints no pods, then every pod has RuntimeDefault at pod level or all containers do (via modern or legacy settings)."
What indicates a problem
- Any line printed by the script is a pod that needs manual review.
- Specifically problematic cases:
POD_SEC_PROFILE=NONEandPOD_OLD_ANNOT=NONE: no pod-level seccomp set.POD_SEC_PROFILEpresent but notRuntimeDefault.POD_OLD_ANNOTpresent but notruntime/default.
- For such pods, inspect their manifests and update them to use
spec.securityContext.seccompProfile.type: RuntimeDefault(or ensure all containers do), then rerun the script to confirm they disappear from the output.