← Policy catalog
</> ValidatingAdmissionPolicy · Apache-2.0

Has No Seccomp Profile Set

container-seccomp-profile-restricted

severityModerate resourceContainers productKubernetes bundles2

A container with no seccomp profile enforced at pod or container level runs with no syscall filter, leaving the full kernel syscall surface reachable for container escape and privilege escalation.

Rejects unless

(has(object.spec.os) &&
 has(object.spec.os.name) &&
 object.spec.os.name.lowerAscii() == "windows") ||
(variables.podTypeAllowed &&
 object.spec.containers.all(c,
   !has(c.securityContext) ||
   !has(c.securityContext.seccompProfile) ||
   !has(c.securityContext.seccompProfile.type) ||
   variables.allowedSeccompTypes.exists(t, t == c.securityContext.seccompProfile.type)
 )
) || (!variables.podTypePresent &&
 object.spec.containers.all(c,
   has(c.securityContext) &&
   has(c.securityContext.seccompProfile) &&
   has(c.securityContext.seccompProfile.type) &&
   variables.allowedSeccompTypes.exists(t, t == c.securityContext.seccompProfile.type)
 )
)

spec.containers[*].securityContext.seccompProfile.type must be "RuntimeDefault" or "Localhost". Container fields may be undefined only when the Pod-level spec.securityContext.seccompProfile.type is set to "RuntimeDefault" or "Localhost"; otherwise every container must set its own to one of those values.

Variables

allowedSeccompTypes

["RuntimeDefault","Localhost"]

podTypePresent

has(object.spec.securityContext) && has(object.spec.securityContext.seccompProfile) && has(object.spec.securityContext.seccompProfile.type)

podTypeAllowed

variables.podTypePresent && variables.allowedSeccompTypes.exists(t, t == object.spec.securityContext.seccompProfile.type)

Remediation

Set the seccomp type to RuntimeDefault, or to Localhost naming a profile loaded on the node, on each container or once at pod level. Fields: spec.containers[*].securityContext.seccompProfile.type, spec.securityContext.seccompProfile.type.

Applies to

  • pods · v1 · CREATE, UPDATE

Manifest

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: container-seccomp-profile-restricted
  annotations:
    kubeapt.io/uuid: "150f6c7c-1a9f-4b17-a7f2-c8737684752a"
    security.kubeapt.io/displayName: "Has No Seccomp Profile Set"
    security.kubeapt.io/description: "A container with no seccomp profile enforced at pod or container level runs with no syscall filter, leaving the full kernel syscall surface reachable for container escape and privilege escalation."
    security.kubeapt.io/resource: "Containers"
    security.kubeapt.io/severity: "Moderate"
    security.kubeapt.io/remediation: "Set the seccomp type to RuntimeDefault, or to Localhost naming a profile loaded on the node, on each container or once at pod level. Fields: spec.containers[*].securityContext.seccompProfile.type, spec.securityContext.seccompProfile.type."
    security.kubeapt.io/product: "Kubernetes"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:
      - ''
      apiVersions:
      - v1
      operations:
      - CREATE
      - UPDATE
      resources:
      - pods
  variables:
  - name: allowedSeccompTypes
    expression: |
      ["RuntimeDefault","Localhost"]
  - name: podTypePresent
    expression: |
      has(object.spec.securityContext) && has(object.spec.securityContext.seccompProfile) && has(object.spec.securityContext.seccompProfile.type)
  - name: podTypeAllowed
    expression: |
      variables.podTypePresent && variables.allowedSeccompTypes.exists(t, t == object.spec.securityContext.seccompProfile.type)
  validations:
  - expression: |
      (has(object.spec.os) &&
       has(object.spec.os.name) &&
       object.spec.os.name.lowerAscii() == "windows") ||
      (variables.podTypeAllowed &&
       object.spec.containers.all(c,
         !has(c.securityContext) ||
         !has(c.securityContext.seccompProfile) ||
         !has(c.securityContext.seccompProfile.type) ||
         variables.allowedSeccompTypes.exists(t, t == c.securityContext.seccompProfile.type)
       )
      ) || (!variables.podTypePresent &&
       object.spec.containers.all(c,
         has(c.securityContext) &&
         has(c.securityContext.seccompProfile) &&
         has(c.securityContext.seccompProfile.type) &&
         variables.allowedSeccompTypes.exists(t, t == c.securityContext.seccompProfile.type)
       )
      )
    message: |
      spec.containers[*].securityContext.seccompProfile.type must be "RuntimeDefault" or "Localhost". Container fields may be undefined only when the Pod-level spec.securityContext.seccompProfile.type is set to "RuntimeDefault" or "Localhost"; otherwise every container must set its own to one of those values.

Save it as container-seccomp-profile-restricted.yaml — the commands below assume that name.

Validate with kubeapt

Check a workload against this one policy, before anything is installed on a cluster.

$ kubeapt validate -p ./container-seccomp-profile-restricted.yaml -r ./workload.yaml

Or without the file, from the published policy set — -r takes a directory too:

$ kubeapt policies download && kubeapt validate --policy-name container-seccomp-profile-restricted -r ./manifests

Or against every namespace in the cluster your kubeconfig points at:

$ kubeapt validate --policy-name container-seccomp-profile-restricted -A