The Seccomp Profile Is Set To docker/default In Pod
More Info:
Applying the default seccomp profile restricts the syscalls available to containers, reducing the kernel attack surface.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify pods and collect their seccomp settings
- On any machine with kubectl access, list all pods and export their specs for review:
kubectl get pods -A -o yaml > /tmp/all-pods-with-seccomp.yaml
- Alternatively, spot-check a specific namespace:
kubectl get pods -n NAMESPACE -o yaml > /tmp/namespace-pods-with-seccomp.yaml
- On any machine with kubectl access, list all pods and export their specs for review:
-
Review pods for explicit or inherited seccomp profiles
- Search for
seccompProfileusage:grep -n "seccompProfile:" -n /tmp/all-pods-with-seccomp.yaml - For pods of concern, inspect their security context to see whether they use the runtime default profile:
kubectl get pod POD_NAME -n NAMESPACE -o yaml
- In the output, look under:
.spec.securityContext.seccompProfile.spec.containers[].securityContext.seccompProfile.spec.initContainers[].securityContext.seccompProfile
Check thattype: RuntimeDefaultis set where required.
- Search for
-
Decide which workloads must use the runtime default seccomp profile
- For each pod/workload, determine:
- Whether it is security-sensitive (public-facing, multi-tenant, or runs with elevated permissions).
- Whether it needs a custom seccomp profile (e.g., legacy or low-level system tools) or can use the runtime default (
type: RuntimeDefault).
- Document any justified exceptions (pods that must use a custom profile or cannot yet be restricted) along with business/technical rationale.
- For each pod/workload, determine:
-
Update pod or controller manifests to use the runtime default seccomp profile
- For pods you decide should use the default profile and that currently lack it, edit the owning resource (Deployment/StatefulSet/DaemonSet/Job/CronJob, or Pod manifest) on any machine with kubectl access:
kubectl edit deployment DEPLOYMENT_NAME -n NAMESPACE
- Under
spec.template.spec.securityContext(pod-level) or under each container’ssecurityContext, add or adjust:securityContext:seccompProfile:type: RuntimeDefault - For workloads managed via GitOps or other IaC, make the same change in the source manifest instead of using
kubectl edit, then apply:kubectl apply -f PATH/TO/MANIFEST.yaml
- For pods you decide should use the default profile and that currently lack it, edit the owning resource (Deployment/StatefulSet/DaemonSet/Job/CronJob, or Pod manifest) on any machine with kubectl access:
-
Reconcile pods to pick up the new seccomp settings
- For controllers (Deployments, etc.), ensure a rollout occurs so new pods use the updated security context:
kubectl rollout restart deployment DEPLOYMENT_NAME -n NAMESPACEkubectl rollout status deployment DEPLOYMENT_NAME -n NAMESPACE
- For standalone Pods not managed by a controller, delete and recreate them from the updated manifest:
kubectl delete pod POD_NAME -n NAMESPACEkubectl apply -f UPDATED_POD_MANIFEST.yaml
- For controllers (Deployments, etc.), ensure a rollout occurs so new pods use the updated security context:
-
Verify the applied seccomp profile on running pods
- After updates and rollouts, confirm that pods are now using the runtime default profile:
kubectl get pod POD_NAME -n NAMESPACE -o yaml | \grep -A3 "seccompProfile"
- Confirm that relevant pods show:
seccompProfile:type: RuntimeDefault
- Optionally, re-export and re-scan cluster-wide to ensure coverage:
kubectl get pods -A -o yaml | grep -A3 "seccompProfile"
- After updates and rollouts, confirm that pods are now using the runtime default profile:
Using kubectl
# 1) List all pods and their seccompProfile (any machine with kubectl access)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.seccompProfile.type}{"\t"}{.spec.securityContext.seccompProfile.localhostProfile}{"\n"}{end}' \
| column -t
How to read this:
- Column 1: Namespace
- Column 2: Pod name
- Column 3: Pod-level
seccompProfile.type - Column 4: Pod-level
seccompProfile.localhostProfile
Indications of a potential problem:
typeis empty (no pod-level seccomp profile set).typeisUnconfined.typeisLocalhostbutlocalhostProfiledoes not correspond to your approved/default profile.- You rely only on container-level seccomp instead of pod-level, or there is inconsistency across pods.
# 2) For a specific pod, show full securityContext for pod and containers
# Replace <namespace> and <pod-name> with actual values
kubectl get pod -n <namespace> <pod-name> -o yaml | \
sed -n '/^spec:/,/^status:/p'
Focus on:
securityContext:
seccompProfile:
type: RuntimeDefault # desired example per benchmark
# or other type/value currently used
and any securityContext.seccompProfile under each container.
Indications of a potential problem:
- Missing
seccompProfileat pod level and at all container levels. - Explicit
type: Unconfined. typevalues that do not align with your chosen default (RuntimeDefaultper remediation).
# 3) Identify pods with explicitly Unconfined seccomp at pod level
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.securityContext.seccompProfile.type}{"\n"}{end}' \
| awk '$3=="Unconfined"'
Any line returned here represents a pod that explicitly disables seccomp at the pod level and should be reviewed.
# 4) Identify pods with no pod-level seccompProfile
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.securityContext.seccompProfile.type}{"\n"}{end}' \
| awk 'NF<3 || $3==""'
Pods listed here rely entirely on container-level configuration or runtime defaults; they require manual review to ensure this is acceptable and consistent with the intent to use the default seccomp profile.
# 5) Inspect container-level seccomp configuration for a specific pod
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.securityContext.seccompProfile.type}{"\t"}{.securityContext.seccompProfile.localhostProfile}{"\n"}{end}'
Indications of a potential problem:
typeisUnconfined.typeis empty and pod-level also has noseccompProfile.- Mixed usage within the same pod (some containers configured, some not), unless this is an intentional design and documented.
Verification after you make any manifest changes (no automated fix here):
# Re-run summary to confirm pods you changed now show the expected type (e.g., RuntimeDefault)
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.seccompProfile.type}{"\t"}{.spec.securityContext.seccompProfile.localhostProfile}{"\n"}{end}' \
| column -t
Review that the pods you modified now have seccompProfile.type: RuntimeDefault (or your chosen default) and that no unexpected Unconfined or empty profiles remain, subject to your security policy and workload requirements.
Automation
#!/usr/bin/env bash
# Report Pods whose seccomp profile is NOT explicitly set to RuntimeDefault
# Run on any machine with kubectl access and current-context pointing to the target cluster.
set -euo pipefail
echo "Namespace,Pod,ContainerType,ContainerName,SeccompType,SeccompLocalhostProfile"
# 1) Check pod-level securityContext.seccompProfile
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| (
.metadata.namespace as $ns
| .metadata.name as $podname
| .spec.securityContext.seccompProfile.type // "UNSET" as $type
| .spec.securityContext.seccompProfile.localhostProfile // "UNSET" as $lp
| [$ns,$podname,"pod","-", $type, $lp] | @csv
)
'
# 2) Check container-level securityContext.seccompProfile (overrides pod-level)
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| .metadata.namespace as $ns
| .metadata.name as $podname
| (
.spec.containers[]? as $c
| [
$ns,
$podname,
"container",
$c.name,
($c.securityContext.seccompProfile.type // "UNSET"),
($c.securityContext.seccompProfile.localhostProfile // "UNSET")
] | @csv
),
(
.spec.initContainers[]? as $c
| [
$ns,
$podname,
"initContainer",
$c.name,
($c.securityContext.seccompProfile.type // "UNSET"),
($c.securityContext.seccompProfile.localhostProfile // "UNSET")
] | @csv
)
'
How to run (any machine with kubectl access):
chmod +x report-seccomp-runtime-default.sh
./report-seccomp-runtime-default.sh > seccomp-report.csv
Interpretation (what indicates a problem):
-
For this control, you want every workload to use the default runtime seccomp profile:
- Pod-level or container-level
SeccompTypeshould beRuntimeDefault. SeccompLocalhostProfileshould typically beUNSETwhenSeccompTypeisRuntimeDefault.
- Pod-level or container-level
-
Lines that are potential problems and need manual review:
-
SeccompTypeisUNSET
→ No explicit seccomp profile set; behavior depends on kubelet/container runtime defaults. -
SeccompTypeis anything other thanRuntimeDefault(e.g.Localhost,Unconfined)
→ Not using the default runtime profile; check if this is an intentional exception. -
SeccompTypeisLocalhostwith a customSeccompLocalhostProfile
→ Strong indication of non-default profile; validate the policy and exception process.
-
Use the CSV to filter for non-compliant entries, for example:
# Show all lines that are not explicitly RuntimeDefault
grep -v 'RuntimeDefault' seccomp-report.csv