Skip to main content

LD_PRELOAD Hijacking in GPU Containers: The Technique Behind Two Critical NVIDIA CVEs

For executives

LD_PRELOAD is a Linux mechanism that has existed for decades. It is used legitimately by developers for debugging and by security tools for monitoring. CVE-2025-23266 (NVIDIAScape) demonstrated that setting LD_PRELOAD in a Dockerfile is sufficient to achieve root code execution on a GPU host, because the NVIDIA Container Toolkit hook inherits and uses the environment variable before the container sandbox is established. This article explains the mechanism, why GPU container environments are particularly exposed to it, and why it is difficult to detect with tools that operate at the container layer.

What LD_PRELOAD does

When a Linux process starts, the dynamic linker loads the libraries the executable depends on. LD_PRELOAD is an environment variable that instructs the dynamic linker to load a specified library before all others — before the standard C library, before anything else.

The security implication: if an attacker can set LD_PRELOAD for a privileged process, they can cause that process to load and execute attacker-controlled code before the process's own code runs.

Why the NVIDIA Container Toolkit hook was vulnerable

When a GPU container starts with the NVIDIA runtime, the Container Toolkit registers the createContainer hook. Before the patch, this hook inherited environment variables directly from the container image. If the container image set LD_PRELOAD to a path within its own filesystem, the nvidia-ctk binary — running with host root privileges — would load whatever library that path pointed to.

The hook also ran with its working directory set to the container's root filesystem, meaning the library path could be relative. The attacker does not need to stage the payload anywhere on the host.

The exploit:

FROM nvidia/cuda:12.4.1-base
ENV LD_PRELOAD=/tmp/payload.so
COPY payload.so /tmp/

Three lines. Push the image. Schedule it on a GPU node. Root on the host.

Why image scanning misses sophisticated implementations

The obvious implementation — setting LD_PRELOAD explicitly in a Dockerfile ENV instruction — is detectable. Less obvious implementations are not:

Setting LD_PRELOAD in a base image layer via a malicious base image distributed via a public registry. Setting LD_PRELOAD via a shell script that runs at container entrypoint, setting the variable dynamically at runtime. Using LD_AUDIT, another dynamic linker environment variable that produces similar injection capability.

Detection at the right layer

LD_PRELOAD injection via OCI hooks is invisible to process monitoring that begins after the container is running. The hook executes before the container process tree is established. Detecting it requires observing hook behaviour directly — what libraries the nvidia-ctk process loads, what environment variables it inherits, what filesystem paths its dynamic linker accesses.