[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3575":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":35,"readmeContent":36,"aiSummary":37,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":38,"discoverSource":39},3575,"Copy-Fail-CVE-2026-31431-Kubernetes-PoC","Percivalll\u002FCopy-Fail-CVE-2026-31431-Kubernetes-PoC","Percivalll","PoC: fully unprivileged container escape to node-level code execution on Kubernetes via CVE-2026-31431 page-cache corruption + shared image layers. Validated on Alibaba Cloud ACK, Amazon EKS and Google GKE.","",null,"C",167,26,59,0,2,38,6,4.29,"Other",false,"main",true,[25,26,27,28,29,30,31,32,33,34],"container-escape","cve-2026-31431","eks","exploit","kubernetes","linux-kernel","privilege-escalation","proof-of-concept","security-research","vulnerability","2026-06-12 02:00:51","# Copy Fail (CVE-2026-31431) — Kubernetes Container Escape PoC\n\nA proof-of-concept demonstrating how a **fully unprivileged container** can achieve **node-level code execution** on Kubernetes by exploiting the CVE-2026-31431 Linux kernel page-cache corruption bug through shared container image layers.\n\nThe core attack primitive is: **any privileged DaemonSet sharing image layers with an attacker-controlled container can be weaponized for container escape**. This PoC uses kube-proxy as one concrete example, but the technique generalizes to any privileged workload on the cluster.\n\nValidated on **Alibaba Cloud ACK**, **Amazon EKS**, and **Google GKE** — an unprivileged pod writes `[*] success` to the host filesystem via the privileged kube-proxy DaemonSet:\n\n| Alibaba Cloud ACK (kernel 6.6.88) | Amazon EKS (kernel 6.12.79) | Google GKE (kernel 6.12.68) |\n|:--:|:--:|:--:|\n| ![ACK](docs\u002Fack-poc-res.png) | ![EKS](docs\u002Feks-poc-res.png) | ![GKE](docs\u002Fgke-poc-res.png) |\n\n> **Disclaimer:** This repository is published for educational and defensive purposes only. Use it exclusively on systems you own or have explicit authorization to test.\n\n## Background\n\nCVE-2026-31431 (\"Copy Fail\") is a Linux kernel vulnerability in the page-cache Copy-on-Write (CoW) path. An `AF_ALG` splice race allows an unprivileged process to corrupt the page-cache pages of a **read-only** file. The corruption persists in the kernel page cache and is visible to every process that subsequently reads or executes the file — including processes in other containers or on the host.\n\nFor full details on the original vulnerability, see [copy.fail](https:\u002F\u002Fcopy.fail\u002F).\n\n## Attack Principle\n\nThe attack exploits three properties that commonly coexist in Kubernetes clusters:\n\n1. **Kernel page-cache corruption (CVE-2026-31431)** — an unprivileged process can overwrite the in-memory cached pages of any file it can open read-only.\n2. **Image layer sharing** — container runtimes (containerd, CRI-O) use overlay filesystems where identical image layers map to the same page-cache pages across containers.\n3. **Privileged DaemonSets** — many clusters run DaemonSets with elevated privileges (`privileged: true`, `hostNetwork: true`, broad capabilities, etc.) that periodically execute binaries from their image.\n\nWhen these conditions align, an unprivileged pod can corrupt a binary in a shared image layer, and a privileged DaemonSet on the same node will unknowingly execute the corrupted binary with its elevated privileges — achieving full node-level code execution.\n\n**The vulnerability target is NOT limited to kube-proxy.** Any privileged DaemonSet (monitoring agents, CNI plugins, log collectors, security agents, etc.) whose container image shares layers with an attacker-controlled image is a viable target.\n\n## How It Works\n\nThe attack chain has three stages: **page-cache corruption**, **cross-container propagation**, and **privileged execution**.\n\n### 1. Page-Cache Corruption via AF_ALG Splice Race\n\nThe kernel's `AF_ALG` (crypto) subsystem exposes a socket-based interface for userspace cryptographic operations. The exploit abuses a race condition in how the kernel handles `splice()` from a file into an AF_ALG socket:\n\n1. Open the target binary **read-only**.\n2. Create an AF_ALG AEAD socket bound to `authencesn(hmac(sha256),cbc(aes))`.\n3. Send a small payload chunk through the AF_ALG socket with `MSG_MORE`, telling the kernel to expect more data.\n4. `splice()` the target file's contents from an fd → pipe → AF_ALG socket.\n5. Due to the CoW bug, the kernel **writes the attacker's payload bytes into the target file's page-cache pages** instead of properly isolating them.\n\nThe exploit repeats this for each 4-byte window until the entire target binary's cached pages are overwritten with a custom payload.\n\nNo write permission to the file is needed. The file on disk is unchanged — only the in-memory page cache is corrupted.\n\n### 2. Cross-Container Propagation via Image Layer Sharing\n\nContainer runtimes use overlay filesystems. When two containers share the same image layer, the kernel serves their file reads from the **same page-cache pages**.\n\nThe attacker builds their PoC image `FROM` the same base image as the target privileged DaemonSet. Because both containers share the same overlay lower-dir, binaries in the shared layer map to **identical page-cache pages**.\n\nWhen the unprivileged PoC container corrupts a binary's page cache, the corruption is immediately visible to the privileged container on the same node — with zero cross-container communication.\n\n### 3. Privileged Execution by the Target DaemonSet\n\nWhen the privileged DaemonSet next executes any corrupted binary (through its normal operation cycle), the kernel loads the corrupted page-cache pages. The attacker's payload runs with the DaemonSet's full privileges — potentially including:\n\n- Full root on the node\n- All capabilities\n- Access to host namespaces (network, PID, mount)\n\nThe payload in this PoC (`payload\u002Fpayload.c`) simply mounts the host root filesystem and writes a marker file to `\u002Froot\u002Fres` as proof of node-level code execution.\n\n### Attack Flow Diagram\n\n```\n┌──────────────────────────┐     ┌──────────────────────────┐\n│   PoC Container          │     │   Privileged DaemonSet   │\n│   (unprivileged)         │     │   (e.g. kube-proxy,      │\n│                          │     │    monitoring agent, etc.)│\n│  1. Open target binary   │     │                          │\n│     (read-only)          │     │                          │\n│                          │     │                          │\n│  2. AF_ALG splice race   │     │                          │\n│     corrupts page cache  │     │                          │\n│          │               │     │                          │\n└──────────┼───────────────┘     └──────────────────────────┘\n           │                                  │\n           ▼                                  │\n  ┌─────────────────────┐                     │\n  │  Kernel Page Cache   │                     │\n  │                      │◄────────────────────┘\n  │  Shared-layer binary │     3. DaemonSet executes the\n  │  (CORRUPTED)         │        corrupted binary\n  │  contains attacker's │        → loads corrupted pages\n  │  payload bytes       │        → payload runs with\n  └─────────────────────┘           DaemonSet's privileges\n```\n\n## Validated Cloud Environments\n\nThe PoC has been successfully validated on the following managed Kubernetes platforms:\n\n### Alibaba Cloud ACK\n\n| Property | Value |\n|----------|-------|\n| Platform | Alibaba Cloud Container Service for Kubernetes (ACK) |\n| Kubernetes | v1.35.2 |\n| Node Kernel | 6.6.88-4.2.alnx4.x86_64 |\n| kube-proxy | `registry-cn-*.ack.aliyuncs.com\u002Facs\u002Fkube-proxy:v1.35.2-aliyun.1` |\n| Base Image | `registry.k8s.io\u002Fkube-proxy:v1.35.2` (upstream) |\n| Root Device | `\u002Fdev\u002Fvda3` (ext4) |\n\n![ACK PoC Result](docs\u002Fack-poc-res.png)\n\n### Amazon EKS\n\n| Property | Value |\n|----------|-------|\n| Platform | Amazon Elastic Kubernetes Service (EKS) |\n| Kubernetes | v1.35.4 |\n| Node Kernel | 6.12.79-101.147.amzn2023.x86_64 |\n| kube-proxy | `***.dkr.ecr.***.amazonaws.com.cn\u002Feks\u002Fkube-proxy:v1.35.3-eksbuild.2` |\n| Base Image | `public.ecr.aws\u002Feks-distro-build-tooling\u002Feks-distro-minimal-base-iptables:2026-03-11-1773190710.2023` |\n| Root Device | `\u002Fdev\u002Fnvme0n1p1` (xfs) |\n\n![EKS PoC Result](docs\u002Feks-poc-res.png)\n\n### Google GKE\n\n| Property | Value |\n|----------|-------|\n| Platform | Google Kubernetes Engine (GKE) |\n| Kubernetes | v1.35.3-gke.1234000 |\n| Node OS | Container-Optimized OS (COS) 125, BUILD_ID 19216.220.72 |\n| Node Kernel | 6.12.68+ x86_64 |\n| kube-proxy | `us-central1-artifactregistry.gcr.io\u002Fgke-release\u002Fgke-release\u002Fkube-proxy:v1.35.3-gke.1234000` |\n| Base Image | Same as kube-proxy (GKE provider-managed Artifact Registry image) |\n| Root Device | `\u002Fdev\u002Fdm-0` (ext2, read-only); `\u002Fdev\u002Fsda1` (ext4, writable stateful partition) |\n| Marker Path | `\u002Fmnt\u002Fstateful_partition\u002Fcopyfail-res` |\n\n![GKE PoC Result](docs\u002Fgke-poc-res.png)\n\nIn all three cases, an **unprivileged** PoC pod successfully wrote the `[*] success` marker file to the host filesystem — proving node-level code execution through the privileged kube-proxy DaemonSet.\n\nFor the complete walkthroughs (image layer analysis, build steps, deployment):\n\n- **EKS**: [docs\u002Feks-poc.md](docs\u002Feks-poc.md)\n- **GKE**: [docs\u002Fgke-poc.md](docs\u002Fgke-poc.md)\n\n## kube-proxy as a Concrete Example\n\nThis PoC uses kube-proxy as the target because it is one of the most common privileged DaemonSets in Kubernetes clusters. Three variants are provided:\n\n- **Default (ACK \u002F upstream)**: built `FROM registry.k8s.io\u002Fkube-proxy:v1.35.2` (see `Dockerfile`)\n- **EKS**: built `FROM public.ecr.aws\u002Feks-distro-build-tooling\u002Feks-distro-minimal-base-iptables:2026-03-11-1773190710.2023` (see `Dockerfile.eks`)\n- **GKE**: built `FROM us-central1-artifactregistry.gcr.io\u002Fgke-release\u002Fgke-release\u002Fkube-proxy:v1.35.3-gke.1234000` (see `Dockerfile.gke`)\n\nAll variants corrupt binaries like `\u002Fusr\u002Fsbin\u002Fipset`, `\u002Fusr\u002Fsbin\u002Fnft`, `\u002Fusr\u002Fsbin\u002Fxtables-legacy-multi`, and `\u002Fusr\u002Fsbin\u002Fxtables-nft-multi`.\n\n**Important caveats:**\n\n- kube-proxy only invokes `ipset` when configured in **ipvs** mode. The default mode (`iptables`) does not use `ipset`. See [kubernetes\u002Fenhancements#5495](https:\u002F\u002Fgithub.com\u002Fkubernetes\u002Fenhancements\u002Fblob\u002Fmaster\u002Fkeps\u002Fsig-network\u002F5495-deprecate-ipvs-mode-in-kube-proxy\u002FREADME.md) for the ipvs deprecation plan.\n- Some managed Kubernetes distributions (e.g. certain cloud providers) run kube-proxy as a **non-privileged** container, which limits the impact of the escape.\n- The PoC targets multiple binaries (`ipset`, `nft`, `xtables-legacy-multi`, `xtables-nft-multi`) to cover different proxy modes, but whether they get invoked depends on cluster configuration.\n\n**If kube-proxy is not privileged in your cluster, the attack principle still holds** — you just need to identify a different privileged DaemonSet that shares image layers with a base image you can build from.\n\n### Generalizing to Other Targets\n\nTo adapt this PoC to a different privileged DaemonSet:\n\n1. Identify a privileged DaemonSet running on the cluster (monitoring agents, CNI plugins, log collectors, etc.).\n2. Build your PoC image `FROM` the same base image used by that DaemonSet.\n3. Identify binaries in the shared layer that the DaemonSet will execute during its normal operation.\n4. Corrupt those binaries' page cache using the exploit.\n\n## Repository Structure\n\n```\n.\n├── cmd\u002Fcopyfail\u002Fmain.go          # Entry point; embeds compiled payload\n├── internal\u002F\n│   ├── exploit\u002F\n│   │   ├── exploit.go            # Core exploit: AF_ALG splice race loop\n│   │   └── patch.go              # Splits payload into 4-byte patch windows\n│   └── alg\u002F\n│       └── alg.go                # AF_ALG AEAD socket abstraction\n├── payload\u002F\n│   ├── payload.c                 # ACK\u002Fupstream payload (mount \u002Fdev\u002Fvda3 ext4)\n│   ├── payload-eks.c             # EKS payload (NVMe\u002FXen device auto-detection)\n│   ├── payload-gke.c             # GKE payload (COS\u002FUbuntu device auto-detection)\n│   └── nolibc\u002F                   # Kernel's tiny libc for static, no-dependency payloads\n├── deploy\u002F\n│   ├── poc.yaml                  # Kubernetes Deployment manifest (ACK\u002Fupstream)\n│   ├── poc-eks.yaml              # EKS Deployment manifest\n│   └── poc-gke.yaml              # GKE Deployment manifest\n├── Dockerfile                    # ACK\u002Fupstream: FROM registry.k8s.io\u002Fkube-proxy\n├── Dockerfile.eks                # EKS: FROM eks-distro-minimal-base-iptables\n├── Dockerfile.gke                # GKE: FROM gke-release\u002Fkube-proxy\n├── Makefile                      # Build orchestration (includes *-eks and *-gke targets)\n└── docs\u002F\n    ├── eks-poc.md                # EKS PoC full walkthrough\n    ├── gke-poc.md                # GKE PoC full walkthrough\n    ├── ack-poc-res.png           # ACK validation screenshot\n    ├── eks-poc-res.png           # EKS validation screenshot\n    └── gke-poc-res.png           # GKE validation screenshot\n```\n\n## Prerequisites\n\n- Go 1.25+\n- A cross-compiler for the nolibc payload (default: `x86_64-linux-gnu-gcc`)\n- Docker \u002F Buildx\n- A Kubernetes cluster with a **privileged DaemonSet** that shares image layers with the PoC image (the default example targets kube-proxy)\n- `imagePullPolicy: IfNotPresent` on the target DaemonSet (the Kubernetes default)\n- Linux kernel **before** the CVE-2026-31431 fix\n\n## Building\n\n### ACK \u002F Upstream Kubernetes\n\n```bash\n# Build payload + Go binary\nmake build\n\n# Build Docker image\nmake docker-build\n\n# Build and push to GHCR\nmake docker-push IMAGE=ghcr.io\u002F\u003Cyou>\u002Fcopy-fail-poc TAG=latest\n```\n\n### Amazon EKS\n\n```bash\n# Build EKS payload + Go binary + Docker image\nmake docker-build-eks\n\n# Build and push to GHCR\nmake docker-push-eks IMAGE=ghcr.io\u002F\u003Cyou>\u002Fcopy-fail-poc\n```\n\nFor `arm64` targets (Graviton):\n\n```bash\nmake build-eks CC=aarch64-linux-gnu-gcc GOARCH=arm64\n```\n\n### Google GKE\n\n```bash\n# Build GKE payload + Go binary + Docker image\nmake docker-build-gke\n\n# Build and push to GHCR\nmake docker-push-gke IMAGE=ghcr.io\u002F\u003Cyou>\u002Fcopy-fail-poc\n```\n\nFor `arm64` nodes:\n\n```bash\nmake docker-build-gke CC=aarch64-linux-gnu-gcc GOARCH=arm64 PLATFORM=linux\u002Farm64\n```\n\n## Usage\n\n### Deploy the PoC\n\n```bash\n# ACK \u002F upstream Kubernetes\nkubectl apply -f deploy\u002Fpoc.yaml\n\n# Amazon EKS\nkubectl apply -f deploy\u002Fpoc-eks.yaml\n\n# Google GKE\nkubectl apply -f deploy\u002Fpoc-gke.yaml\n```\n\nThe Deployment creates a single unprivileged pod. It:\n\n1. Runs `\u002Fbin\u002Fcopyfail` to corrupt the page cache of target binaries in the shared image layer.\n2. Sleeps indefinitely so the pod stays running for observation.\n\n### Verify the Escape\n\nAfter the target privileged DaemonSet next executes a corrupted binary (for kube-proxy, this typically happens within seconds due to its reconciliation loop), check the **node**:\n\n```bash\n# SSH into the node, or use a privileged debug pod\n\n# ACK \u002F EKS (writable root filesystem)\ncat \u002Froot\u002Fres\n# Expected output: [*] success\n\n# GKE COS nodes (read-only root, writable stateful partition)\ncat \u002Fmnt\u002Fstateful_partition\u002Fcopyfail-res\n# Expected output: [*] success\n```\n\nThe presence of the marker file on the host filesystem proves that attacker-supplied code executed with node-level privileges — from inside the privileged DaemonSet's container context.\n\n### Clean Up\n\n```bash\nkubectl delete -f deploy\u002Fpoc.yaml      # or poc-eks.yaml \u002F poc-gke.yaml\n\n# On the affected node(s), remove the marker and restart the target DaemonSet:\nrm -f \u002Froot\u002Fres                                     # ACK \u002F EKS\nrm -f \u002Fcopyfail-res \u002Fmnt\u002Fstateful_partition\u002Fcopyfail-res  # GKE COS nodes\n# For kube-proxy: delete the pod to force image layer re-read\nkubectl delete pod -n kube-system -l k8s-app=kube-proxy --field-selector spec.nodeName=\u003Cnode>\n```\n\n## Customizing the Payload\n\nThe default payload (`payload\u002Fpayload.c`) is a validation-only program that writes a marker file. To build a custom payload:\n\n1. Edit `payload\u002Fpayload.c`. The program is built against `nolibc` (the kernel's minimal C library) for a static, dependency-free binary.\n2. Run `make payload` to cross-compile.\n3. The compiled payload is embedded into the Go binary via `\u002F\u002Fgo:embed`.\n\n## Affected Versions\n\n- **Linux kernel**: All versions before the CVE-2026-31431 patch.\n- **Kubernetes**: Any version using an unpatched node kernel. The vulnerability is in the kernel, not in Kubernetes itself. Kubernetes merely provides the execution context (shared image layers + privileged DaemonSets) that elevates the impact from local page-cache corruption to full container escape.\n\n## Mitigation\n\n- **Patch the kernel.** This is the definitive fix.\n- **Enable image layer isolation.** Some runtimes support per-container filesystem snapshots that prevent page-cache sharing.\n- **Minimize privileged DaemonSets.** Reduce the number of workloads running with elevated privileges; use the principle of least privilege.\n- **Drop unnecessary capabilities** from DaemonSets that don't strictly require `privileged: true`.\n- **Restrict pod scheduling** to prevent untrusted workloads from landing on nodes running privileged DaemonSets with shared base images.\n- **Use distinct base images** for privileged workloads to reduce the chance of layer sharing with untrusted containers.\n\n### Mitigation Examples\n\n- **vArmor built-in mitigation rule**: [copy-fail-mitigation](https:\u002F\u002Fgithub.com\u002Fbytedance\u002FvArmor\u002Fblob\u002Fmain\u002Fwebsite\u002Fdocs\u002Fguides\u002Fpolicies_and_rules\u002Fbuilt_in_rules\u002Fvulnerability_mitigation.md#copy-fail-mitigation) blocks the exploit vector by preventing containers from creating `AF_ALG` sockets. The rule is available through the AppArmor and BPF enforcers.\n- **Kubernetes eBPF mitigation**: [iwanhae\u002Fcopyfail-ebpf-k8s](https:\u002F\u002Fgithub.com\u002Fiwanhae\u002Fcopyfail-ebpf-k8s) provides an eBPF-based Kubernetes mitigation example for CVE-2026-31431.\n\n## Credits\n\n- **CVE-2026-31431 discovery and disclosure**: [Theori \u002F Xint](https:\u002F\u002Fcopy.fail\u002F)\n- **Cross-platform C payload**: [Tony Gies](https:\u002F\u002Fgithub.com\u002Ftgies\u002Fcopy-fail-c) (LGPL-2.1-or-later OR MIT)\n- **nolibc**: Linux kernel selftests (`tools\u002Finclude\u002Fnolibc\u002F`)\n\n## License\n\nThe Go exploit code in this repository is provided as-is for research purposes.\n\nThe payload (`payload\u002Fpayload.c`) is derived from [copy-fail-c](https:\u002F\u002Fgithub.com\u002Ftgies\u002Fcopy-fail-c) and is dual-licensed under **LGPL-2.1-or-later** OR **MIT**. See [LICENSE-LGPL](LICENSE-LGPL) and [LICENSE-MIT](LICENSE-MIT).\n","该项目展示了如何利用CVE-2026-31431 Linux内核漏洞，使一个完全无特权的容器在Kubernetes环境中实现节点级代码执行。核心功能是通过共享镜像层和利用特权DaemonSet（如kube-proxy）来实现容器逃逸。技术上，它利用了Linux内核中的页面缓存损坏漏洞，结合容器运行时的镜像层共享机制，使得无特权进程能够篡改只读文件的内存缓存页。此PoC已在阿里云ACK、Amazon EKS和Google GKE等主流Kubernetes平台上验证成功。适用于安全研究、漏洞测试以及防御性演练场景，帮助用户了解并防范此类攻击风险。","2026-06-11 02:54:42","CREATED_QUERY"]