Sep 15, 2026·6 min read·57 visits
An interaction flaw between snap-confine and systemd-tmpfiles allows a local unprivileged attacker to take control of tracking directories in /tmp after they are cleaned up, permitting sandbox escape and host root access.
CVE-2026-3888 is a critical local privilege escalation vulnerability arising from the insecure interaction between Canonical's snap-confine helper binary and systemd-tmpfiles within the world-writable /tmp directory.
CVE-2026-3888 represents a local privilege escalation vulnerability within the snapd package manager, specifically affecting the snap-confine helper binary. This vulnerability arises not from an isolated programming error, but from the insecure interaction between snap-confine and the systemd-tmpfiles utility in the world-writable /tmp directory. An unprivileged local attacker can leverage this condition to escape the snap sandbox and obtain administrative root privileges on default installations of Ubuntu Desktop.
To provide confined security boundaries, snap-confine constructs an isolated mount namespace for each snap application. This namespace configuration relies on directory hierarchies created inside the host's /tmp folder, particularly a hidden subdirectory named /tmp/.snap. This subdirectory tracks mount configurations and supports writable overlays, known as mimics, for restricted paths within the read-only snap environment.
The attack surface exists because /tmp is a world-writable directory. When systemd-tmpfiles cleans up aged directories, the tracking directory can be removed while the parent directory remains. An unprivileged local user inside the sandbox can subsequently recreate the directory under their own ownership, creating a mechanism to hijack subsequent administrative mount processes.
The root cause of CVE-2026-3888 is a privilege chaining vulnerability (CWE-268) involving an insecure temporary directory (CWE-377) and a time-of-check to time-of-use (TOCTOU) race condition (CWE-367). The vulnerability is triggered during the daily execution of systemd-tmpfiles-clean.service, which targets inactive files and directories within /tmp. On Ubuntu 24.04 LTS, directories inactive for more than 30 days are purged, while Ubuntu 25.10+ reduces this threshold to 10 days.
While a user remains active within a snap sandbox, the primary temporary directories are continuously accessed. However, the root-owned subdirectory /tmp/.snap, which maintains the state of host mimic mounts, remains inactive and unmodified. This inactivity triggers the cleanup mechanism of systemd-tmpfiles, which recursively deletes /tmp/.snap without evaluating whether active namespace handles still reference the parent container.
Because the host's /tmp directory is configured with the sticky bit (mode 1777), any local user can create new subdirectories inside it. Once systemd-tmpfiles deletes the root-owned /tmp/.snap, an unprivileged user process can instantly recreate /tmp/.snap with their own user identifier (UID). This transition of directory ownership from root to an unprivileged user constitutes the fundamental control-flow breakdown.
The vulnerability's remediation requires modifying the systemd-tmpfiles configuration to prevent the deletion of critical snapd state directories. The original, vulnerable configuration lacked explicit exclusions for the internal tracking directories of snap-private-tmp.
The corrected configuration file, /usr/lib/tmpfiles.d/snapd.conf, introduces specific exclusion rules using the X and x type flags. These directives instruct systemd-tmpfiles to traverse the parent directories without deleting the structure of the enclosed mimic-tracking subdirectories.
# Vulnerable configuration lacked exclusion for .snap subdirectories
# Patched configuration (/usr/lib/tmpfiles.d/snapd.conf):
D! /tmp/snap-private-tmp 0700 root root -
# Exclude private tmp subdirectories from cleanup
X /tmp/snap-private-tmp
X /tmp/snap-private-tmp/*/tmp
x /tmp/snap-private-tmp/*/tmp/.snapAdditionally, the associated TOCTOU vulnerability identified within the Rust-based coreutils rm implementation involved a path-based directory traversal. The fix implemented in commits such as 1183529cd2deafb38bed3b6bf212357b68eefa41 transitioned the deletion process from path-based APIs to file-descriptor-relative calls using openat and unlinkat with the AT_REMOVEDIR flag, preventing directory substitution mid-execution.
The exploitation process requires local access and is structured around a timed race condition. The attacker first establishes a shell inside a confined snap application environment, such as Firefox, and monitors the target /tmp/.snap folder. By continuously interacting with the primary /tmp directory, the attacker keeps it active while waiting for systemd-tmpfiles to delete the untouched /tmp/.snap subdirectory after the 10 or 30-day threshold has passed.
Upon deletion, the attacker immediately recreates /tmp/.snap under their own UID and populates it with a target mimic structure, such as /tmp/.snap/usr/lib/x86_64-linux-gnu. During the next execution of snap-confine, the attacker blocks the execution of the SUID-root helper by restricting the receive buffers on the redirected standard error socket, permitting a slow-stepped inspection of the initialization sequence.
When snap-confine attempts to mount the system libraries, the attacker performs a directory swap using the RENAME_EXCHANGE flag or standard directory replacement. This forces snap-confine to bind-mount the user-controlled library path into the sandbox's /usr/lib/x86_64-linux-gnu directory, allowing the injection of a custom dynamic linker (ld.so) or a preload shared library that executes arbitrary code as root when a SUID process runs inside the container.
The impact of CVE-2026-3888 is a full compromise of system integrity, confidentiality, and availability. Successful exploitation allows an unprivileged local user to escape the strict confinement of the snap sandbox (AppArmor and Seccomp) and execute arbitrary code on the host operating system with administrative root privileges.
This vulnerability is assigned a CVSS v3.1 score of 7.8 (High) with the vector CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H. The changed scope parameter reflects the ability of the exploit to cross the security boundary established by the snapd mount namespace and influence the hyper-privileged host execution state.
While the EPSS score of 0.00383 reflects a low probability of automated exploitation in the wild, the local nature of the vulnerability makes it highly valuable for targeted privilege escalation campaigns. No user interaction is required to trigger the exploit, and the attack relies entirely on deterministic system processes.
Remediation requires upgrading the snapd package to the patched versions issued by Canonical. For Ubuntu 24.04 LTS, the vulnerability is addressed in 2.73+ubuntu24.04.2. Security administrators must verify that their systems are running versions equal to or greater than the specified patch level to ensure that the malformed tmpfiles configuration is replaced.
If immediate updates cannot be deployed, the risk can be mitigated by manually editing /usr/lib/tmpfiles.d/snapd.conf to append the exclusion rules for /tmp/snap-private-tmp/*/tmp/.snap. After editing the file, administrators must reload the configuration by executing sudo systemctl restart systemd-tmpfiles-clean.service to apply the updated parameters.
Organizations should also audit their environments for the brief window when Ubuntu 25.10 shipped the Rust-based coreutils, ensuring that standard GNU coreutils or patched uutils builds are enforced to mitigate the secondary recursive deletion flaw.
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
snapd Canonical | < 2.73+ubuntu24.04.2 | 2.73+ubuntu24.04.2 |
snapd Canonical | < 2.73+ubuntu25.10.1 | 2.73+ubuntu25.10.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-268 |
| Attack Vector | Local |
| CVSS Score | 7.8 |
| EPSS Score | 0.00383 |
| Exploit Status | poc |
| KEV Status | Not Listed |
Privilege Chaining
CVE-2026-115906 is a cryptographic authentication bypass vulnerability in the Rust zip library (zip-rs/zip2) affecting versions from 0.6.0 prior to 9.0.0. In the WinZip AE-x AES decryption reader implementation within src/aes.rs, the HMAC-SHA1-80 authentication tag is only validated when the internal byte counter (data_remaining) decrements to exactly zero. Because this counter is initialized from the unauthenticated compressed_size header field, an attacker can craft a ZIP archive where the entry stream hits premature physical end-of-file (EOF) before data_remaining reaches zero, causing the reader to return Ok(0) and skip HMAC verification entirely.
CVE-2026-115908 (GHSA-hjqx-j4rw-g7xv) is a high-severity path traversal and link-following vulnerability in the Rust zip library (zip-rs/zip2) affecting versions >= 7.2.0 and < 9.0.0. Because ZipArchive::extract and ZipArchive::extract_unwrapped_root_dir validate symbolic link targets solely via lexical prefix comparisons rather than resolving intermediate filesystem links, an attacker who knows or can guess the absolute extraction path can construct multi-hop symlink chains that escape the destination directory, enabling arbitrary file creation and overwrite with the privileges of the extracting process.
CVE-2026-115907 is an uncontrolled resource consumption vulnerability in the Rust zip crate (versions 5.1.0 through 8.6.0, and 9.0.0 pre-releases) when compiled with the optional legacy-zip feature flag. The vulnerability resides in the legacy decompression decoders—Shrink, Reduce, and Implode—which directly pass an archive-declared 64-bit uncompressed size from a ZIP64 extended information extra field to Vec::reserve() before validating the compressed data stream. By supplying a malformed ZIP archive with a declared uncompressed size exceeding isize::MAX (such as u64::MAX), an unauthenticated attacker can trigger an unhandled capacity overflow panic in the Rust standard library allocator, terminating the calling thread or aborting the entire process.
Twisted versions up to and including 26.4.0 are vulnerable to an unauthenticated remote denial-of-service attack via the HTTP/2 Rapid Reset technique (a variant of CVE-2023-44487). The HTTP/2 connection handler in twisted.web processes pipelined HEADERS and RST_STREAM frames sequentially within the same TCP segment. Because the request dispatch and synchronous rendering occur upon receiving the StreamEnded event before the subsequent StreamReset event is evaluated, an attacker can force the server to expend CPU cycles rendering responses while immediately evicting stream state to bypass concurrent stream limits.
An inefficient algorithmic complexity vulnerability exists in the npm package decode-uri-component prior to version 0.5.1. When processing malformed URI strings containing invalid percent-escape sequences, the library falls back to a custom decoder that collects distinct percent-encoded runs into a dictionary and executes a full-string regular expression replacement for each entry. Supplying a payload with thousands of distinct percent-encoded sequences alongside a malformed escape triggers quadratic O(K * L) execution time, starving the single-threaded Node.js event loop and resulting in an unauthenticated Denial of Service.
Open Neural Network Exchange (ONNX) versions 1.4.0 prior to 1.22.0 contain a null pointer dereference (CWE-476) and a signed-to-unsigned integer conversion error (CWE-195) in the shape inference functions for the Scan operator. When processing an untrusted ONNX model, the functions ScanInferenceFunction, ScanInferenceFunction_opset8, and ScanInferenceFunction_opset9 fail to validate the presence and value of the required num_scan_inputs attribute. Omitting the attribute results in a direct null pointer dereference that crashes the host process via SIGSEGV, while supplying a negative value triggers an integer wrap-around during type narrowing that leads to an unhandled allocation failure. Notably, models containing a negative num_scan_inputs value bypass standard validation via onnx.checker.check_model().