Microsoft Defender for Cloud · Azure Kubernetes Service
Immutable (read-only) root filesystem should be enforced for containers
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Immutable (read-only) root filesystem should be enforced for containers" check?
Inspects pods running on an AKS cluster and flags any container whose 'securityContext.readOnlyRootFilesystem' is not set to true, meaning the container can write to its own root file system at runtime. The check is driven by the Azure Policy add-on for AKS (Gatekeeper v3) and only evaluates clusters that have the add-on installed, so a cluster without the add-on is simply unassessed rather than compliant. It looks at the container specification, not at what a process actually writes, and it does not cover mounted volumes: a container can still write to an explicitly declared emptyDir or persistent volume while keeping its root file system read-only. By default it skips system namespaces such as kube-system and gatekeeper-system.
Why does "Immutable (read-only) root filesystem should be enforced for containers" matter?
A writable root file system lets an attacker who lands code execution inside a container drop new binaries, overwrite application files, add entries to PATH or persist a foothold that survives a process restart. Read-only roots turn that into a much harder problem: the compromise cannot tamper with the running image, so malware has nowhere durable to live and many privilege-escalation toolkits fail outright. For a regulated workload this is the difference between an isolated, ephemeral incident and one where an investigator cannot trust that any file in the container is the file you shipped, which is exactly the kind of integrity gap that forces a wider breach disclosure.
How do I fix "Immutable (read-only) root filesystem should be enforced for containers"?
- Set 'readOnlyRootFilesystem: true' in the container 'securityContext' of every Deployment, StatefulSet and Job, then add an emptyDir or persistent volume for any path the app legitimately writes to, such as temp directories or caches, so the process still works.
- Install the Azure Policy add-on so the rule is enforced cluster-wide: 'az aks enable-addons --addons azure-policy --name <cluster> --resource-group <rg>'.
- Assign the built-in definition by looking up its id rather than pasting a GUID, then set the effect to Deny so non-compliant pods are rejected on admission: 'pid=$(az policy definition list --query "[?displayName=='Kubernetes cluster containers should run with a read only root file system'].name" -o tsv)' then 'az policy assignment create --name aks-readonly-rootfs --policy "$pid" --scope <cluster-resource-id> --params '{"effect":{"value":"Deny"}}''.
Remediation script · bash
# 1. Turn on the Azure Policy add-on so Gatekeeper starts auditing the cluster.
az provider register --namespace Microsoft.PolicyInsights
az aks enable-addons --addons azure-policy \
--resource-group rg-prod --name aks-prod
# Confirm the policy and gatekeeper pods are running.
kubectl get pods -n kube-system -l app=azure-policy
kubectl get pods -n gatekeeper-system
# 2. Assign the built-in pod security baseline initiative in AUDIT first.
# Look the initiative up by its exact display name, never paste a GUID.
SCOPE=$(az aks show -g rg-prod -n aks-prod --query id -o tsv)
SETID=$(az policy set-definition list \
--query "[?displayName=='Kubernetes cluster pod security baseline standards for Linux-based workloads'].name" -o tsv)
az policy assignment create \
--name aks-pod-baseline \
--policy-set-definition "$SETID" \
--scope "$SCOPE" \
--params '{"effect":{"value":"audit"},"excludedNamespaces":{"value":["kube-system","gatekeeper-system","azure-arc"]}}'
# 3. Fix the workloads (in each pod spec, securityContext):
# privileged: false | runAsNonRoot: true | runAsUser: 1000
# allowPrivilegeEscalation: false | readOnlyRootFilesystem: true
# capabilities: { drop: ["ALL"] } and add back only what is needed.
# 4. Once audit is clean except for named exceptions, ENFORCE.
az policy assignment update --name aks-pod-baseline \
--set parameters.effect.value=deny Full walkthrough (console steps, edge cases and verification) in the lesson Enforce AKS pod security.
Is "Immutable (read-only) root filesystem should be enforced for containers" a false positive?
A workload that must write directly to its root file system, for example a legacy application that recreates its own configuration on startup and cannot be repointed at a mounted volume, will keep flagging. The correct exception is to leave that one container writable and exclude it narrowly using the policy's 'excludedContainers' or 'excludedNamespaces' parameter, keeping the read-only default in force everywhere else rather than disabling the assignment outright.
More Azure Kubernetes Service controls
- Azure Kubernetes Service clusters should have Defender profile enabled
- Azure Kubernetes Service clusters should have the Azure Policy add-on for Kubernetes installed
- Azure running container images should have vulnerabilities resolved (powered by Microsoft Defender Vulnerability Management)
- Container CPU and memory limits should be enforced
- Container images should be deployed from trusted registries only
- Container with privilege escalation should be avoided
- Containers sharing sensitive host namespaces should be avoided
- Diagnostic logs in Kubernetes services should be enabled
- Kubernetes API server should be configured with restricted access
- Kubernetes clusters should be accessible only over HTTPS
- Kubernetes clusters should disable automounting API credentials
- Kubernetes clusters should not use the default namespace