Skip to main content
emnode
Compliance Medium severity MCSB PV-2

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"?

  1. 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.
  2. 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>'.
  3. 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.