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

Microsoft Defender for Cloud · Azure Kubernetes Service

Running containers as root user should be avoided

Written and reviewed by Emnode · Last reviewed

What does the recommendation "Running containers as root user should be avoided" check?

Inspects the running workloads on an AKS cluster and flags any pod whose containers start as the root user (UID 0). A container is compliant only when its securityContext sets 'runAsNonRoot' to true, or sets 'runAsUser' to a non-zero UID, at either the pod or the container level. This is a data-plane check on what is actually deployed, so it reads live pod specs rather than the cluster resource definition. It does not analyse the image itself: an image built to run as root still passes if the workload overrides the user at deploy time, and it does not cover privileged mode, host namespaces or capability grants, which are separate recommendations.

Why does "Running containers as root user should be avoided" matter?

A process running as root inside a container is root on the node if it escapes the container boundary. Container breakout bugs in the runtime or kernel surface regularly, and when one lands, a root container hands the attacker the host, every other pod scheduled on that node and the kubelet credentials with it. Even short of a full breakout, root makes routine misconfigurations far easier to weaponise: writable host mounts, package installation and tampering with other processes all become trivial. Dropping to a non-root user contains a compromised workload to its own namespace, which is the difference between one breached service and a breached cluster.

How do I fix "Running containers as root user should be avoided"?

  1. Add a securityContext to each workload that sets 'runAsNonRoot: true' and 'runAsUser' to a non-zero UID (for example 1000), at the pod level so every container inherits it; rebuild images that hard-require root so they can run unprivileged, then redeploy the pods to apply the change.
  2. Enable the Azure Policy add-on so the rule is enforced cluster-wide rather than per workload: 'az aks enable-addons --addons azure-policy --name <cluster> --resource-group <rg>'. This installs Gatekeeper and syncs the built-in constraints into the cluster.
  3. Assign the built-in policy to your clusters in deny mode so non-compliant pods are rejected at admission. Look the definition up by display name rather than hardcoding its GUID: pid=$(az policy definition list --query "[?displayName=='Kubernetes cluster pods and containers should only run with approved user and group IDs'].name" -o tsv) then az policy assignment create --name aks-nonroot --policy "$pid" --scope <cluster-resource-id>.

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 "Running containers as root user should be avoided" a false positive?

Some agents legitimately need UID 0 to do their job, for example a log or metrics collector that reads host paths owned by root, or an init container that adjusts kernel parameters. Rather than weaken the policy, exclude those specific namespaces or pods from the assignment using the policy's excludedNamespaces parameter (kube-system is excluded by default), and keep 'runAsNonRoot' enforced everywhere else so the exception stays scoped to the workloads that genuinely require it.