Join our Newsletter — 33% off our NHI Course
Home› Guides› Kubernetes Storage Security Guide: CSI Drivers, Persistent Volumes,…
Guide Cloud Security

Kubernetes Storage Security Guide: CSI Drivers, Persistent Volumes, Encryption and Tenant Isolation

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 14 min read
On this page

In Kubernetes, the storage layer is where a container most easily reaches the node, another tenant's data or the cloud account behind the cluster. Volumes, PersistentVolumes, StorageClasses, CSI drivers and snapshots are configured by different teams, mostly with defaults, and those defaults favour convenience: dynamically provisioned volumes are deleted with their claim, encryption is often an opt-in driver parameter, and a hostPath mount can expose kubelet credentials. This guide covers the storage objects and their trust boundaries, hostPath and volume type policy, CSI driver privilege and credentials, encryption at rest, tenant isolation, snapshots and data lifecycle. It is written for platform engineers, cluster administrators and security architects running multi-team or multi-tenant clusters on cloud or on-premises storage.

Key takeaways

  • Forbid hostPath for workloads: the Pod Security Standards Baseline profile already does, and the Restricted profile limits Pods to eight volume types; grant exceptions only to named system namespaces.
  • Treat CSI drivers as privileged infrastructure: node plugins run privileged on every node and controller plugins hold cloud or array credentials that can create, attach and delete any volume.
  • Encryption is a StorageClass decision: Kubernetes Secrets encryption does not encrypt volumes; set the driver's encryption and customer-managed key parameters in every StorageClass and remove classes that lack them.
  • Isolate tenants by StorageClass, quota and RBAC: PersistentVolumes, StorageClasses and VolumeSnapshotContents are cluster-scoped, so only administrators should create them.
  • Decide deletion deliberately: the default reclaim policy is Delete, which is good for data minimisation and bad for ransomware recovery; protect production data with Retain plus independent backups.

The storage objects and where trust sits

Kubernetes storage is a chain of API objects and components, each with a different owner and scope. Understanding which are namespaced and which are cluster-scoped is the basis of every access decision in this guide.

Object or componentScopeNormally created bySecurity relevance
Pod volume (emptyDir, configMap, secret, projected, hostPath)Pod specApplication teamshostPath reaches the node filesystem; Secret and ConfigMap volumes are always mounted read-only
PersistentVolumeClaim (PVC)NamespacedApplication teamsRequest for storage; access mode, size and class; subject to namespace quota
PersistentVolume (PV)ClusterProvisioner or administratorPoints at a real disk, share or LUN; a hand-made PV can point at someone else's data
StorageClassClusterPlatform teamHolds driver parameters: encryption, key ID, reclaim policy, mount options, credential references
CSIDriver and CSI pluginsCluster, DaemonSet and DeploymentPlatform team or managed servicePrivileged node plugin on every node; controller plugin with backend credentials
VolumeSnapshot / VolumeSnapshotContent / VolumeSnapshotClassNamespaced / cluster / clusterTeams / controller / platform teamCopies of data with their own deletion policy

The PersistentVolume documentation lists four access modes: ReadWriteOnce (RWO), ReadOnlyMany (ROX), ReadWriteMany (RWX) and ReadWriteOncePod (RWOP). RWO restricts a volume to one node, not one Pod, so several Pods on the same node can still mount it. Use ReadWriteOncePod where a single writer is a security or integrity requirement, and treat RWX shared file systems as shared data stores that need their own permission model.

hostPath and volume type policy

The Kubernetes volumes documentation carries an explicit warning: hostPath "presents many security risks" and should be avoided, with a local PersistentVolume as the alternative. It names the risks: host files can expose privileged credentials such as the kubelet's, or privileged APIs such as the container runtime socket, which can be used for container escape (MITRE ATT&CK T1611 Escape to Host). The same page warns that restricting hostPath to certain directories at admission is only effective when the mount is also read-only, because a read-write host mount can be subverted by the Pod.

  • Enforce Pod Security Standards: the Baseline profile forbids spec.volumes[*].hostPath. The Restricted profile goes further and permits only configMap, csi, downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected and secret volumes. Label namespaces with pod-security.kubernetes.io/enforce=restricted where workloads allow it. See the Kubernetes Admission Control Guide.
  • Handle the real exceptions: log collectors, CNI and CSI node plugins and monitoring agents legitimately need host paths. Keep them in dedicated system namespaces, allow-list the exact paths in a policy engine (Kyverno, Gatekeeper or ValidatingAdmissionPolicy), and require readOnly: true wherever the agent only reads.
  • Block raw device access: volumeMode: Block presents an unformatted device to the Pod, and privileged containers can read node disks directly (ATT&CK T1006 Direct Volume Access). Restrict privileged Pods and block-mode claims to approved workloads.
  • Watch subPath: CVE-2021-25741 allowed a symlink exchange through a subPath mount to reach the host filesystem. It was fixed in kubelet 1.19.15, 1.20.11, 1.21.5 and 1.22.2; the advisory's interim mitigation was to disable the VolumeSubpath feature gate and stop less-trusted users running containers as root. Old node pools are where this still matters.
  • Generic ephemeral volumes create PVCs: the documentation notes that anyone who can create Pods can create PVCs indirectly through an ephemeral volume, even without PVC permissions. Namespace PVC quotas still apply; reject them by admission if that does not fit your model.

CSI drivers: privilege and credentials

The Container Storage Interface moved storage code out of Kubernetes into drivers maintained by storage and cloud vendors. Most in-tree drivers are gone: the volumes documentation records, for example, that the in-tree gcePersistentDisk driver was deprecated in v1.17 and removed in v1.28. A CSI driver has two halves with very different risk.

ComponentRuns asHoldsHardening
Node plugin (DaemonSet)Privileged container on every node with host mounts of the kubelet plugin directories and devicesAbility to mount, format and read any volume attached to the nodePin images by digest, scan and patch them like node components, restrict who can edit the DaemonSet
Controller plugin and sidecars (external-provisioner, external-attacher, external-snapshotter, external-resizer)Deployment, usually in kube-system or a vendor namespaceCloud IAM role or storage array credentials that create, attach, snapshot and delete volumesWorkload identity instead of static keys, least-privilege IAM scoped to tagged volumes, network policy to the array API
StorageClass secret referencesKubernetes Secrets read by the sidecarsPer-operation credentialsSeparate namespace, RBAC limited to the driver service account, encryption at rest for Secrets

The kubernetes-csi documentation defines StorageClass parameters that point sidecars at Secrets for each operation: csi.storage.k8s.io/provisioner-secret-name, controller-publish-secret-name, node-stage-secret-name, node-publish-secret-name, controller-expand-secret-name and controller-modify-secret-name, each with a matching -namespace key. Values can be templates such as ${pvc.namespace}, and node-publish values can even use PVC annotations. That is powerful and risky: a template that resolves to a namespace the tenant controls lets the tenant choose which credential the driver uses. Prefer fixed secret names in an administrator-owned namespace unless per-tenant credentials are a deliberate design.

The controller's cloud identity is a non-human identity with broad data reach. If it is a static access key in a Secret, anyone who can read that Secret can snapshot and copy every volume in the account (ATT&CK T1552.007 Container API, then T1530 Data from Cloud Storage). In the Tesla Kubernetes cryptojacking incident, an exposed cluster console gave attackers cloud credentials held in the cluster. Use the provider's workload identity for the controller service account. See the Kubernetes NHI Security Guide and the Kubernetes Secrets Security Guide.

Encryption at rest and in transit

Encrypting Secrets in etcd with an EncryptionConfiguration protects API objects only. Volume data is encrypted, or not, by the storage backend, and the CSI driver exposes that choice as StorageClass parameters.

DriverParameterBehaviour per driver documentation
AWS EBS CSIencrypted, kmsKeyIdencrypted defaults to false; without kmsKeyId the region's default AWS-managed key is used. ext4EncryptionSupport only enables the fscrypt feature and does not encrypt files by itself
Azure Disk CSIdiskEncryptionSetID, diskEncryptionTypePoints the disk at a disk encryption set for customer-managed keys, optionally with platform and customer keys together
Google Compute Engine PD CSIdisk-encryption-kms-keyEncrypts new disks with a customer-managed Cloud KMS key
On-premises (Ceph RBD, arrays)Driver specificCeph CSI supports per-volume encryption with a key management service; arrays often encrypt drives below the CSI layer. See the Ceph Security guide
  • Encryption on by default in the class, not the account: account-level defaults (such as EBS encryption by default) are a useful backstop, but the StorageClass is what auditors and admission policy can see.
  • Customer-managed keys where you need revocation: a key you control lets you crypto-shred a decommissioned tenant and see every decrypt in key logs. Grant the CSI controller identity use of the key, not administration of it. See the Database and Storage Encryption Guide.
  • In transit: network file systems (NFS, SMB, CephFS) carry data across the network. Use NFS with Kerberos (krb5p) or TLS where the driver supports it, SMB 3 encryption, and Ceph msgr2 secure mode, and keep storage traffic on a segmented network.
  • Application-level encryption for the most sensitive data, so that a node plugin or backup operator with volume access still sees ciphertext.

Tenant isolation

Namespaces do not isolate storage on their own. Four controls do most of the work:

  1. RBAC on cluster-scoped objects: only the platform team creates PersistentVolumes, StorageClasses, VolumeSnapshotClasses and VolumeSnapshotContents. A user who can create a PV can bind a pre-existing disk or NFS export they should not see. Audit create and update on these resources in every ClusterRole. See the Kubernetes RBAC Guide.
  2. Per-tenant StorageClasses and quota: ResourceQuota supports requests.storage, persistentvolumeclaims and per-class limits (<class>.storageclass.storage.k8s.io/requests.storage). Set the quota for privileged classes to zero in namespaces that should not use them, and decide whether the default StorageClass (annotation storageclass.kubernetes.io/is-default-class) is acceptable for every tenant, since PVCs without a class receive it.
  3. File ownership and labels: fsGroup makes Kubernetes change group ownership of volume contents; fsGroupChangePolicy: OnRootMismatch limits this to when the root does not match. On SELinux nodes, per-Pod MCS labels separate tenants' files; seLinuxChangePolicy controls whether relabelling is recursive or done at mount.
  4. Backend separation: for hard multi-tenancy, give each tenant a separate storage pool, cloud account or array virtual server with its own credentials, rather than relying on Kubernetes objects alone.

Snapshots, reclaim and data lifecycle

The storage-classes documentation states that reclaimPolicy may be Delete or Retain and defaults to Delete; dynamically provisioned PVs inherit it. Recycle is deprecated. With Retain, deleting the PVC leaves the PV and the underlying disk, and the administrator must clean up by hand. VolumeSnapshotClasses have their own deletionPolicy of Delete or Retain.

SettingSecurity benefitRiskUse when
reclaimPolicy DeleteNo orphaned disks holding old dataOne kubectl delete pvc or namespace deletion destroys data (ATT&CK T1485)Caches, scratch and rebuildable data
reclaimPolicy RetainData survives accidental or malicious claim deletionReleased PVs and disks accumulate and keep sensitive dataProduction databases and records, with a reclaim runbook
Snapshot deletionPolicy RetainSnapshot survives deletion of the VolumeSnapshot objectSnapshots outlive retention schedulesRecovery points that must outlast the namespace
Snapshots in the same accountFast restoreSame credentials can delete volume and snapshot together (T1490 Inhibit System Recovery)Never as the only copy

The finalizers kubernetes.io/pvc-protection and kubernetes.io/pv-protection stop a volume in active use being removed under a running Pod, but they do not protect data once the Pod is gone. Snapshots are not backups unless they are copied out of the blast radius of the CSI controller's credentials. See the Kubernetes Backup and Recovery guide. For decommissioning, delete the backend asset, its snapshots and replicas, and where possible destroy the customer-managed key.

Implementation: a phased rollout

  1. Inventory (week 1 to 2): list StorageClasses with their parameters, CSI drivers and versions, PVs with reclaim policy and class, VolumeSnapshotClasses, and every Pod using hostPath or block mode. Flag classes without encryption parameters and released PVs.
  2. Audit-mode policy: label namespaces with pod-security.kubernetes.io/audit=baseline and warn=restricted, and run policy-engine rules for hostPath allow-lists and encrypted classes in audit mode. Collect the violations for two to four weeks.
  3. Fix the classes: create encrypted StorageClasses with customer-managed keys, make one the default, and migrate workloads. Existing unencrypted volumes need a snapshot and restore or an application-level copy into an encrypted class.
  4. Move CSI controllers to workload identity and scope their IAM policies to volumes carrying the cluster's tag. Restrict the namespaces holding driver credentials.
  5. Enforce in rings: enforce Baseline everywhere, then Restricted in new namespaces, then existing ones; deny unencrypted classes at admission. Roll back by switching a namespace label from enforce to warn, which takes effect for new Pods without redeploying.
  6. Lifecycle: set Retain on production classes, add copies of snapshots to a separate account or immutable store, and schedule a monthly review of released PVs and orphaned disks.

Small clusters run by one team can stop at Baseline, encrypted default classes and backups. Large, multi-tenant or regulated platforms need the full set, including per-tenant classes and keys.

Detection and measurement

Kubernetes audit logs record the storage API activity; the cloud or array logs record what the driver did with it. Correlate both. See the Kubernetes Audit Log Detection Guide.

  • Alert on: creation or change of PersistentVolumes, StorageClasses, CSIDriver objects and VolumeSnapshotContents by anyone other than the platform pipeline; Pods with hostPath outside allow-listed namespaces; PVCs bound to manually created PVs; mass deletion of PVCs or snapshots; reads of CSI credential Secrets by identities other than the driver.
  • Backend signals: snapshot sharing or copying to another account, key disable or schedule-deletion events, volumes attached to instances outside the cluster.
MetricTarget
Percentage of PVs in classes with encryption and a customer-managed key100% for production
Pods using hostPath outside allow-listed system namespacesZero
Namespaces enforcing Baseline or Restricted Pod Security100% Baseline; rising Restricted share
Released PVs and orphaned backend disks older than 30 daysZero (NHI Mgmt Group recommendation)
CSI controllers using static cloud keysZero
Production volumes with a tested restore from an off-account copy in the last quarter100%

Common failure patterns

  • Trusting Secrets encryption for volumes: teams configure etcd encryption and assume the data volumes are covered. They are not; check the StorageClass parameters.
  • Default class without encryption: a cluster created years ago keeps an unencrypted default class, and every PVC without a class lands there.
  • hostPath for convenience: a team mounts /var/run or /var/lib/kubelet to debug, leaving a direct route to the runtime socket and kubelet credentials.
  • Broad PV create rights: developers with a custom ClusterRole that includes persistentvolumes can bind an existing disk or NFS export from another team.
  • Static keys in the CSI controller: one Secret read gives snapshot and copy rights over every volume in the cloud account.
  • Snapshots as backups: the same identity that can delete volumes can delete their snapshots, so a ransomware actor or a mistaken script removes both.

Framework mapping

Control areaNIST SP 800-53 Rev. 5NIST CSF 2.0ISO/IEC 27001:2022 Annex ACIS Controls v8.1
Volume encryption and keysSC-28, SC-28(1), SC-12PR.DS-01A.8.24Control 3
hostPath, volume types, CSI privilegeCM-7, AC-6PR.PS-01A.8.9Control 4
RBAC on storage objects, tenant isolationAC-6PR.AA-05A.8.3Control 6
Snapshots, reclaim and backupsCP-9PR.DS-11A.8.13Control 11
Decommissioning and deletionMP-6PR.DS-01A.8.10Control 3

Relevant ATT&CK techniques: T1611 Escape to Host, T1006 Direct Volume Access, T1552.007 Container API, T1530 Data from Cloud Storage, T1485 Data Destruction and T1490 Inhibit System Recovery.

Practitioner checklist

  • Enforce Pod Security Standards Baseline in every namespace and Restricted where workloads allow.
  • Allow-list hostPath per system namespace and path, read-only wherever possible.
  • Make every StorageClass set the driver's encryption and customer-managed key parameters, and deny classes that do not.
  • Limit create and update on PersistentVolumes, StorageClasses and snapshot classes to the platform pipeline.
  • Run CSI controllers with workload identity and IAM scoped to the cluster's volumes.
  • Keep CSI credential Secrets in an administrator namespace, with fixed names rather than tenant-controlled templates.
  • Set Retain for production data and copy snapshots outside the CSI controller's account.
  • Patch CSI driver images and node kubelets on the same cadence as other node components.
  • Review released PVs, orphaned disks and snapshots monthly, and crypto-shred decommissioned tenants.

Standards and references

Related NHI Mgmt Group resources: Kubernetes Security Guide · Kubernetes Secrets Security Guide · Kubernetes Backup and Recovery · Container Runtime Security Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.