container-seccomp-profile-restricted
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.
(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.
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)
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.
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.
Check a workload against this one policy, before anything is installed on a cluster.
$ kubeapt validate -p ./container-seccomp-profile-restricted.yaml -r ./workload.yamlOr 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 ./manifestsOr against every namespace in the cluster your kubeconfig points at:
$ kubeapt validate --policy-name container-seccomp-profile-restricted -A