TOCTOU — short for time-of-check to time-of-use — is a class of race condition bug where a program verifies a property of a resource (a file, a permission, a signature, an identity) and then acts on that resource later, assuming nothing changed in between. The vulnerability lives in the gap between those two moments. If an attacker can modify, replace, or relink the resource during that window, the check that just passed becomes meaningless by the time the operation actually executes. So what is TOCTOU in practical terms? It's the software equivalent of a bank teller verifying your ID, looking away for a second, and then handing the vault key to whoever is standing at the counter when they look back — without checking again. TOCTOU bugs are notoriously hard to spot in code review because each individual line looks correct; the flaw only exists in the timing between two otherwise valid operations.
What Is TOCTOU and Why Does the Order of Operations Matter?
TOCTOU is fundamentally an ordering problem, not a logic problem — the check and the use are individually correct, but the assumption that state is frozen between them is false. Most software is written with an implicit mental model that says "if I just confirmed X is true, X is still true a few instructions later." That assumption holds in a single-threaded, single-actor world. It breaks down the moment another process, thread, container, or attacker has write access to the same resource and can act inside that gap. A classic case is a program that calls access() to check whether the current user has permission to read a file, then calls open() to actually read it a few microseconds later. Between those two syscalls, an attacker with a symlink-swapping script can replace the target file with something else entirely — a technique often called a symlink race. The check was accurate; the use operated on a completely different object.
How Does a Time-of-Check to Time-of-Use Vulnerability Actually Get Exploited?
Exploitation almost always follows the same three-step pattern: identify the check-then-act gap, win the race to substitute the resource, and trigger the vulnerable code path repeatedly to improve the odds of landing inside a narrow timing window. Attackers rarely get one shot — instead they script thousands of rapid attempts, often pairing the race with a symlink, hard link, or a mount-point swap so the substitution itself takes near-zero time. Because the window can be a matter of microseconds, a time-of-check time-of-use vulnerability is frequently dismissed as "theoretical" during code review, right up until someone automates the race with a tight loop and a fast filesystem operation. Tools like symlink() and rename() are attractive to attackers precisely because they're atomic and instantaneous, letting a malicious actor swap a file's identity between the validation call and the privileged operation without the kernel ever seeing an inconsistent intermediate state.
What Does a TOCTOU Race Condition Exploit Look Like in Real Code?
A TOCTOU race condition exploit typically targets code that separates validation from action instead of combining them into a single atomic call. Consider a privileged script that checks whether /tmp/build-output.log is owned by the build user before writing sensitive output to it, then opens that same path for writing moments later. An unprivileged attacker on the same host can, immediately after the ownership check passes, delete /tmp/build-output.log and replace it with a symlink pointing at /etc/sudoers or an SSH authorized_keys file. If the write happens with elevated privileges, the attacker has just turned a logging routine into an arbitrary file overwrite primitive. The fix is never "check harder" — it's to eliminate the gap entirely, typically by opening the file first with safe flags (like O_NOFOLLOW and O_EXCL) and then validating the already-open file descriptor, so there's no separate object left to swap.
Why Are File System Race Conditions So Common in Build and CI Pipelines?
File system race conditions show up disproportionately in CI/CD and build tooling because these systems are built around exactly the pattern TOCTOU exploits: check a dependency or artifact, then fetch, build, or execute it in a later step. A pipeline might verify a package's checksum or signature during a "validate" stage and then pull the actual artifact from a shared cache, temp directory, or registry mirror during a "build" stage — two operations separated by network calls, queueing, and parallel job scheduling that can span seconds or minutes, not microseconds. That's a huge window compared to a local syscall race, and it's exactly the kind of gap that supply chain attacks exploit: a compromised or malicious package is substituted after it passes an integrity check but before it's actually pulled into the build. Shared, world-writable temp directories used by build agents make this worse, since any co-located job or container can potentially interfere with artifacts belonging to another job during that gap.
What Is a Well-Known TOCTOU Attack Example?
One of the most cited TOCTOU attack examples is CVE-2020-15257, involving containerd's containerd-shim, where a process namespace check and the subsequent use of that namespace weren't tightly bound, allowing a container to reach a host-level abstract Unix socket under the right conditions — a timing and trust-boundary gap rather than a missing permission check outright. Another widely taught example is the classic /tmp symlink race in Unix system utilities from the 1990s and 2000s, where setuid-root programs created temporary files by checking if a path existed and then creating it, letting local attackers pre-create a symlink to /etc/passwd and have root-owned processes overwrite it. Package managers have their own version of this problem: if a manifest's hash is checked against a registry response, but the actual binary is downloaded in a separate, later request, an attacker positioned to intercept or race that second request can serve different bytes than what was verified — a pattern security researchers now discuss explicitly under the TOCTOU umbrella when analyzing software supply chain integrity.
How Is TOCTOU Different From Other Race Conditions?
TOCTOU is a specific subtype of race condition defined by its two-phase structure — a check followed by a dependent use — rather than by generic concurrent access to shared state. General race conditions can corrupt data or produce inconsistent output when two threads write to the same variable simultaneously; TOCTOU is narrower and usually security-relevant because it specifically undermines a trust decision: a permission check, a signature verification, or an integrity validation. That distinction matters for defenders because the fix isn't generic locking — it's collapsing the check and the use into a single atomic operation wherever the underlying platform allows it, using primitives like openat2() with RESOLVE_NO_SYMLINKS, file descriptor–based operations instead of path-based ones, or content-addressed storage where the "check" (the hash) and the "use" (the fetch) are mathematically the same operation rather than two sequential ones.
How Safeguard Helps
Safeguard is built around closing exactly this kind of gap in the software supply chain, where validation and consumption of artifacts, dependencies, and build outputs are too often separated by time, network hops, and shared infrastructure. Rather than treating a checksum or signature check as a point-in-time event that's trusted indefinitely afterward, Safeguard ties verification directly to content-addressed identity, so what gets checked is provably the same thing that gets used — there's no substitutable object left in between. In CI/CD environments, Safeguard monitors build and deployment pipelines for the shared-cache and shared-temp-directory conditions that make file system race conditions possible, flags stages where artifact validation and artifact consumption are decoupled across time or process boundaries, and helps teams re-architect those flows around atomic, descriptor-based operations instead of fragile path-based check-then-act sequences. For organizations securing their build pipelines against supply chain tampering, that means TOCTOU-class gaps get caught during design and CI review, not discovered after an attacker has already won the race.