This page describes a highlighted problem produced by the Docker and Kubernetes Security scanner plugin.
You could find more details on the internal page: Cloud (IaC) Security plugin
If this project has been helpful to you, please consider giving it a ⭐ on GitHub to help others discover it.
Problem
Using disallowed volume types (e.g., hostPath, legacy in-tree volumes, or raw device mounts) can break container isolation and enable privilege escalation or node compromise.
Description
When a pod can mount arbitrary host paths or devices, an attacker who gains code execution in that pod may:
- Read or modify sensitive host files (credentials, kubelet data, logs).
- Interact with container/runtime sockets (e.g.,
/var/run/*sock) to escalate privileges. - Persist or laterally move by planting files on the node.
Legacy in-tree storage plugins also widen the attack surface and bypass centralized governance.
The Restricted Pod Security level allows only API/CSI-mediated, isolated volume types:configMap, secret, downwardAPI, projected, emptyDir, ephemeral (generic ephemeral volumes), persistentVolumeClaim, and csi.
These do not expose arbitrary host paths/devices and can be controlled by cluster policy (read-only mounts, quotas, StorageClasses, etc.).
Solution
- Allow only the safe volume types listed above.
- Prefer
readOnly: trueforconfigMap,secret,downwardAPI, andprojectedmounts. - Use
emptyDirfor scratch space; considersizeLimit(andmedium: Memoryonly when truly needed). - Use
ephemeralorpersistentVolumeClaim(backed by approved CSI drivers) for durable data. - Enforce at admission time with Pod Security Restricted (and, if needed, Kyverno/OPA policies to allowlist specific StorageClasses/CSI drivers).
Problematic code
apiVersion: apps/v1
kind: Deployment
metadata:
name: risky-deployment
spec:
replicas: 1
selector:
matchLabels:
app: risky
template:
metadata:
labels:
app: risky
spec:
containers:
- name: app
image: alpine
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
- name: host-etc
mountPath: /host/etc
readOnly: true
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock # Direct access to runtime socket
type: Socket
- name: host-etc
hostPath:
path: /etc # Arbitrary host filesystem access
type: DirectoryVerified code
apiVersion: apps/v1
kind: Deployment
metadata:
name: safe-deployment
spec:
replicas: 1
selector:
matchLabels:
app: safe
template:
metadata:
labels:
app: safe
spec:
containers:
- name: app
image: alpine
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: app-config
mountPath: /etc/app/config
readOnly: true
- name: db-creds
mountPath: /var/run/secrets/db
readOnly: true
- name: cache
mountPath: /var/cache/app
- name: data
mountPath: /var/lib/app
volumes:
- name: app-config
configMap:
name: app-config
- name: db-creds
secret:
secretName: db-creds
- name: cache
emptyDir:
sizeLimit: 256Mi
- name: data
persistentVolumeClaim:
claimName: app-data # Backed by an approved StorageClass/CSI driverSource of the rule: Pod Security Standards