Skip to main content

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

Manual Steps
  1. 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"}'
  2. 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 pod
    kubectl -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.
  3. Decide the policy per workload

    • For each pod type (usually via its controller: Deployment, DaemonSet, StatefulSet, Job, CronJob):
      • Preferred: enforce RuntimeDefault at pod level.
      • If incompatible: document the justification, consider designing and referencing a specific seccomp profile instead of leaving it unset or fully unconfined.
  4. 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 securityContext with seccompProfile set to RuntimeDefault (or update existing):
    kubectl -n <NAMESPACE> edit deployment <DEPLOYMENT_NAME>
    • In the spec.template.spec section, 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/pod where present once seccompProfile is set.
  5. 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 same securityContext.seccompProfile.type: RuntimeDefault structure, then redeploy through your standard pipeline to avoid drift.
  6. 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}'
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=NONE and POD_OLD_ANNOT=NONE: no pod-level seccomp set.
    • POD_SEC_PROFILE present but not RuntimeDefault.
    • POD_OLD_ANNOT present but not runtime/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.