Dev News Daily ENDE

Kubernetes 1.37 finally lets you mount a volume noexec, and the default was the problem

Two alpha features in Kubernetes v1.37 close a gap that has been sitting in plain sight for years: until now a pod could not ask for its volumes to be mounted with the flags that every hardening guide assumes — noexec, nosuid, nodev. The container runtime and kubelet bind-mounted volumes without them, and there was no field to say otherwise.

The consequence is worth stating plainly, because it undercuts a control many teams believe they already have. You can set readOnlyRootFilesystem: true on a container and still be left with a writable, executable surface: any volume mounted into the pod. A process that has been compromised can drop a binary into that volume, mark it executable and run it. emptyDir is the sharpest case, because it is the most common writable volume in the world's manifests — and the gap was recorded in Kubernetes' own audit trail, including a finding from the 1.24 security audit, without a field to fix it.

Kubernetes 1.37 finally lets you mount a volume noexec, and the default was the problem
Kubernetes 1.37 finally lets you mount a volume noexec, and the default was the problem — Dev News Daily

What you can actually write now

VolumeBindMountOptions adds bindMountOptions to a volume mount, so a /tmp backed by emptyDir can be mounted [noexec, nosuid] and stop being a launch pad. EmptyDirVolumeMode adds a permission mode to the volume itself: set mode: 0750 and only the intended user and group can read or write it, rather than every sidecar sharing the pod. Both are alpha in v1.37 and must be switched on at the API server and the kubelet.

What it means

The interesting part is the failure behaviour, and the two features do not agree. If the mode on emptyDir cannot be honoured, the kubelet falls back to 0777 — the permissive value, silently. For bindMountOptions the design is the opposite: the scheduler uses node-declared features to keep the pod off nodes whose runtime cannot apply the flags, and a kubelet that receives such a pod rejects it instead of running it unprotected.

That difference matters more than either feature. A security control that degrades quietly to "off" is worse than no control, because the manifest now reads as hardened, the review passes, and nothing tells you which nodes ignored it. If you adopt the permission mode, treat it as a request rather than a guarantee until it graduates, and check on the node rather than in the YAML.

Second, this is a reminder that "read-only root filesystem" is a narrower promise than its name. It covers the image layers, not the volumes, and the volumes are where the writable space lives by design. The mount flags are what turns that space into data rather than code.

Third, the roll-out path is the usual alpha calculus. Both gates are off by default, which means a cluster that wants them needs a kubelet change, not just a manifest change — and in managed clusters that is the provider's decision, not yours. The practical move this month is to find every writable volume in your namespaces and write down which of them would need noexec when the flag is available, because that inventory is the work, and it does not depend on the feature gate.

Driven by SIG Node and SIG Storage.