Use KubeFleet to rollout Kernel LPE CVE mitigations
This post shows how to use KubeFleet to simplify the safe rollout of mitigations for CVE-2026-31431 (“Copy Fail”) and CVE-2026-43284 / CVE-2026-43500 (“DirtyFrag”) and CVE-2026-46300 (“Fragnesia”) across multiple Kubernetes clusters. This vulnerability allows a container to escalate to root on the node and impacts Linux nodes until mitigations are applied. Existing nodes require either a node image upgrade or the self-service DaemonSet mitigation shown in this post.
The DaemonSet used in this post originates from the Azure Kubernetes Service (AKS) advisory and detailed mitigation guide for per-cluster application which can be found in GitHub Issue 5753.
Before you begin
Before following the instructions in this post you must first configure your clusters as members of a fleet, which requires one cluster to act as the hub cluster.
Configure a cluster as your KubeFleet hub cluster (instructions) and make sure you have the kubeconfig downloaded.
Add remaining Kubernetes clusters as member clusters (instructions).
Add labels to member clusters that can be used for rollout grouping. In this example we label the three clusters using dev, test, prod as the stages.
kubectl label membercluster my-member-cluster-01 upgroup=dev
kubectl label membercluster my-member-cluster-02 upgroup=test
kubectl label membercluster my-member-cluster-03 upgroup=prod
Apply mitigation
If you are unable to patch your nodes to an OS release that fixes the CVEs you can apply a DaemonSet that disables the vulnerable kernel modules.
The DaemonSet is deployed into its own Namespace on each cluster, making it easy to discern intent and easier to distribute across clusters.
Given how DaemonSets function, the protection is applied to the node, even though we don’t use the kube-system Namespace as shown in the original AKS mitigation guide.
For the rollout we’ll use KubeFleet’s resource placement features:
- Multi-cluster selection for a resource via ClusterResourcePlacement.
- Controlled rollout of the resource via ClusterStagedUpdateRun and ClusterStagedUpdateStrategy
Step 1: Create the mitigation Namespace and DaemonSet
Create the 01-kernel-lpe-mitigate.yaml file with the following contents. The DaemonSet blocks vulnerable modules covered by the CVEs.
apiVersion: v1
kind: Namespace
metadata:
name: kernel-lpe-cve-mitigate-ns
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kernel-lpe-mitigate
namespace: kernel-lpe-cve-mitigate-ns
labels:
app: kernel-lpe-mitigate
purpose: security-mitigation
spec:
selector:
matchLabels:
app: kernel-lpe-mitigate
template:
metadata:
labels:
app: kernel-lpe-mitigate
spec:
hostPID: true
priorityClassName: system-node-critical
nodeSelector:
kubernetes.io/os: linux
tolerations:
- operator: Exists
containers:
- name: mitigate
image: mcr.microsoft.com/cbl-mariner/busybox:2.0
command:
- /bin/sh
- -c
- |
echo "=== Kernel LPE Module Mitigation ==="
echo "Covers: CVE-2026-31431 (algif_aead), DirtyFrag (esp4/esp6/rxrpc)"
MODULES="algif_aead esp4 esp6 rxrpc"
for mod in $MODULES; do
if ! grep -qs "install ${mod} /bin/false" /host/etc/modprobe.d/*.conf 2>/dev/null; then
printf "install %s /bin/false\nblacklist %s\n" "$mod" "$mod" >> /host/etc/modprobe.d/disable-kernel-lpe.conf
echo "Blocked ${mod}"
else
echo "${mod} already blocked"
fi
if chroot /host grep -q "^${mod} " /proc/modules 2>/dev/null; then
if chroot /host modprobe -r "$mod" 2>/dev/null; then
echo "Unloaded ${mod}"
else
echo "WARNING: Could not unload ${mod} (in use). Reboot node."
fi
fi
done
echo "=== Mitigation complete. Sleeping ==="
sleep infinity
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
memory: 32Mi
securityContext:
privileged: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
type: Directory
Stage the mitigation namespace and DaemonSet on the KubeFleet hub cluster.
kubectl apply -f 01-kernel-lpe-mitigate.yaml
Step 2: Create a ClusterResourcePlacement
Create a placement manifest 02-fleet-pick-clusters-mitigation.yaml that selects all KubeFleet member clusters (PickAll) as suitable to receive the Namespace and its DaemonSet. We set the strategy to External so we can define and control the rollout order for clusters, which we will do in following steps.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterResourcePlacement
metadata:
name: kernel-lpe-cve-mit-ns-place
spec:
resourceSelectors:
- group: ""
version: v1
kind: Namespace
name: kernel-lpe-cve-mitigate-ns
policy:
placementType: PickAll
strategy:
type: External
Apply the placement on KubeFleet hub cluster.
kubectl apply -f 02-fleet-pick-clusters-mitigation.yaml
You can validate how many member clusters will receive the mitigation using this command.
kubectl get clusterresourceplacement kernel-lpe-cve-mit-ns-place -o jsonpath="{.status.conditions[?(@.type=='ClusterResourcePlacementScheduled')].message}"
The message in the response shows how many clusters were selected.
found all cluster needed as specified by the scheduling policy, found 3 cluster(s)
Step 3: Create a ClusterStagedUpdateStrategy
A strategy is used to define the rollout order and soak duration per rollout stage. Note that all selected clusters must be in a stage. This is determined by the labels set of the cluster when it was added to the fleet.
In this sample 03-fleet-mitigation-rollout-strategy.yaml we have three stages, with a 4 hour soak time between each stage. You can also add approvals if required.
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateStrategy
metadata:
name: kernel-lpe-cve-mit-ds-strategy
spec:
stages:
- name: stage1
labelSelector:
matchLabels:
upgroup: dev
afterStageTasks:
- type: TimedWait
waitTime: 4h
maxConcurrency: 1
- name: stage2
labelSelector:
matchLabels:
upgroup: test
afterStageTasks:
- type: TimedWait
waitTime: 4h
maxConcurrency: 1
- name: stage3
labelSelector:
matchLabels:
upgroup: prod
Apply the strategy on KubeFleet hub cluster.
kubectl apply -f 03-fleet-mitigation-rollout-strategy.yaml
Step 4: Start rollout
Finally, create a ClusterStagedUpdateRun 04-fleet-mitigation-rollout-run.yaml to begin the rollout.
NOTE: To start the rollout later, set
statetoInitialize. You can patch the resource toRunto begin rollout (see below).
apiVersion: placement.kubernetes-fleet.io/v1
kind: ClusterStagedUpdateRun
metadata:
name: kernel-lpe-cve-mit-ds-rollout
spec:
placementName: kernel-lpe-cve-mit-ns-place
stagedRolloutStrategyName: kernel-lpe-cve-mit-ds-strategy
state: Run
Apply the update run on KubeFleet hub cluster. If you have Run as the state, the rollout begins.
kubectl apply -f 04-fleet-mitigation-rollout-run.yaml
Step 5: Monitor and control rollout
Use the following command to retrieve the status of the rollout. Inspect the conditions and stageStatuses arrays to review progress.
kubectl get clusterstagedupdaterun kernel-lpe-cve-mit-ds-rollout -o yaml
NOTE: You can also use the preview version of KubeFleet’s Headlamp plugin to help monitor and control the rollout. Connect it to the KubeFleet hub cluster to use.
If you want to stop the rollout, you can patch the update run:
kubectl patch clusterstagedupdaterun kernel-lpe-cve-mit-ds-rollout --type merge -p '{"spec":{"state":"Stop"}}'
Restart the rollout by patching the update run:
kubectl patch clusterstagedupdaterun kernel-lpe-cve-mit-ds-rollout --type merge -p '{"spec":{"state":"Run"}}'
Step 6: Validate mitigation is applied
Select clusters in your fleet that have received the mitigation and run the following check.
kubectl logs -n kernel-lpe-cve-mitigate-ns -l app=kernel-lpe-mitigate
If the mitigation is applied successfully you should see.
=== Kernel LPE Module Mitigation ===
Covers: CVE-2026-31431 (algif_aead), DirtyFrag (esp4/esp6/rxrpc)
Blocked algif_aead
Blocked esp4
Blocked esp6
Blocked rxrpc
=== Mitigation complete. Sleeping ===
NOTE: In some cases where the module is in use, the node will require a reboot. The log message will indicate this is required.
Step 7: Roll back or remove
If issues occur, or the DaemonSet is no longer required as the node image has been updated to a permanently patched release, you can remove the mitigation DaemonSet by deleting the ClusterResourcePlacement on the KubeFleet hub cluster.
kubectl delete clusterresourceplacement kernel-lpe-cve-mit-ns-place
Summary
In this post we’ve seen how you can use KubeFleet to:
- Apply an immediate mitigation across all clusters via DaemonSet.
- Use a controlled rollout to reduce risk, allowing testing on clusters in batches.
- No node reboot required when module not in use.
If you’re interested to learn more about KubeFleet, consider joining a KubeFleet community call.