A Time of Check Time of Use (TOCTOU) vulnerability is a flaw in which a program checks the state of a resource and then acts on it as a separate step, allowing the state to change in between. The check returns a truthful answer, the answer expires, and the program acts on stale information. MITRE classifies it as CWE-367.

The everyday version is ordinary enough to be unremarkable. You spot an empty table in a busy cafe, confirm it is free, and walk over with your drink to find someone else sitting there. Nothing you observed was wrong. It simply stopped being true during the walk. Software makes the same mistake constantly, and when the program doing the walking holds administrative privileges, the consequences stop being a matter of standing awkwardly with a coffee.

This guide covers what makes the gap exploitable, why symbolic links turn a timing quirk into a privilege escalation route, two worked attacks, and why the standard mitigation advice contains one fix that works and several that only improve the odds. TOCTOU sits in the secure software development portion of the CISSP Common Body of Knowledge, and candidates are expected to recognise it from a scenario description rather than from the acronym.

What is a TOCTOU vulnerability?

TOCTOU describes a specific and very common code shape: verify, then act. A program asks whether it may read a file, whether a path points somewhere safe, whether a balance is sufficient, or whether a record still exists. Having received a satisfactory answer, it proceeds to use the thing it asked about.

The flaw is not in either operation. It is in the assumption joining them, which is that nothing relevant changed in between. On a system running one process with no concurrency, that assumption holds. On any real system it is a guess, and an attacker who can influence the resource can make the guess wrong deliberately.

The check and the use are two separate operations

The essential structure has three parts, and the middle one is invisible in the source code:

  1. Time of check. The program evaluates the resource and gets a result that is accurate at that instant.
  2. The window. An interval of arbitrary length during which the program is not looking at the resource. It may be microseconds. It may be much longer if the program is descheduled, waiting on input, or handling other work.
  3. Time of use. The program acts, applying a decision made against conditions that may no longer exist.

What makes this hard to spot in review is that the window has no representation on the page. A developer reading two adjacent lines sees them as adjacent. The operating system sees two separate system calls with an unbounded scheduling gap between them, and so does an attacker.

Why TOCTOU is a race condition

The vulnerability only produces an exploit when someone else changes the resource inside the window, so the outcome depends on the relative timing of two independent actors. That is the definition of a race condition, and MITRE files CWE-367 as a child of CWE-362, the general class covering concurrent execution using a shared resource without proper synchronisation.

The relationship runs one way, which is a distinction worth holding onto. Every TOCTOU flaw is a race condition. Most race conditions are not TOCTOU flaws: two threads corrupting a shared counter are racing, but nothing was checked and then used. TOCTOU names the particular case where the race is between a validation and the action that validation authorised.

The attacker’s position in that race is far stronger than it first appears. The program must win every time. The attacker only has to win once, can attempt the race continuously, and can often make the window wider by loading the system or forcing the target process to wait.

Most TOCTOU exploitation in file handling runs through symbolic links, and understanding why explains most of the impact.

A symbolic link is a file whose content is a path to another file. When a program opens one, the operating system transparently resolves the link and hands back the target. Unlike a desktop shortcut, which applications treat as an object in its own right, a symlink is followed by default by most file operations. The program usually has no idea it received something other than what it named.

That creates a gap between two things developers habitually conflate: a filename, which is a label that can be repointed at any moment by anyone with write access to the containing directory, and a file, which is the actual object. A check performed on a name is a statement about whatever that name referred to at the time of asking. It is not a durable statement about anything.

The attack pattern follows directly. An attacker who cannot read a protected file creates an ordinary file they own and can manipulate. A privileged program checks that file and finds it acceptable, because at that moment it genuinely is. Before the program acts, the attacker replaces the name with a symbolic link to the protected file. The program follows the link using its own privileges and does the attacker’s reading or writing for them.

This is why TOCTOU is usually discussed as a privilege escalation technique rather than an availability or integrity problem in isolation. The attacker is not breaking the privileged program’s access controls. They are borrowing its authority.

The window, and what can change inside it

The interval between check and use is where every TOCTOU attack lives, and several distinct things can happen there. Not all of them require an attacker:

  • The resource is replaced with a different file carrying the same name.
  • The name is repointed at a symbolic link aimed somewhere sensitive.
  • Permissions or ownership on the resource are altered.
  • The file’s contents are rewritten while the name and metadata stay stable.
  • The resource is deleted, so the program creates a fresh one under conditions it never validated.
  • Another legitimate user on a multi-user system modifies the same resource in good faith.
  • A scheduled job, maintenance task or synchronisation process updates it automatically.

The last two matter more than they are usually given credit for, because they mean a TOCTOU flaw can corrupt data with no attacker present at all. A backup that reads a file mid-write, or a validation that passes before an automated deployment swaps the file underneath it, produces a wrong result through the same defect. This is one reason TOCTOU belongs in an integrity conversation as much as a confidentiality one, and it is the failure mode that formal integrity models address through the concept of the well-formed transaction: a state change that either completes consistently or does not happen.

An attacker’s advantage is that they do not need the window to be long. They need it to be hittable, and it can be attacked in a tight loop indefinitely until it is hit.

Worked example: the backup that copies the password file

Consider an automated backup process running nightly with administrative privileges, copying customer files to a secure location. An attacker with limited access to the system wants the contents of /etc/shadow, which stores password hashes and which their own account cannot read.

The sequence runs like this:

  1. The attacker identifies a file, customer_data.csv, that the backup routinely collects, and establishes when the job runs.
  2. The backup process checks whether it may read customer_data.csv. The check succeeds honestly: the file exists and the process has ample rights.
  3. Inside the window, the attacker deletes the file and creates a symbolic link of the same name pointing at /etc/shadow.
  4. The backup process opens the name and copies the target, following the link with administrative privileges.
  5. The password hashes land in the backup location, where the attacker can read them at leisure and attack them offline.

Two properties of this attack deserve attention, because they generalise well beyond the example.

First, every component behaved correctly. The permission check was accurate. The backup process did exactly what it was built to do. The operating system resolved the symlink exactly as documented. No control was bypassed, which is precisely why no control fired.

Second, the logs look normal. The backup records a successful backup. There is no failed access attempt, no permission denial, no anomalous authentication. Detection has to come from noticing that a backup contains a file it has no business containing, which is a much harder question than the ones monitoring is usually configured to ask.

Note also what the attacker gains: hashes, not passwords. The distinction matters for how urgently this must be treated, and it is why hashing with a strong algorithm and per-user salting changes the economics of the theft without making it harmless.

Worked example: tampering with a firewall configuration

The second pattern targets integrity rather than confidentiality, and it is the more alarming of the two because it subverts a security control itself.

A firewall loads its ruleset from a configuration file on a schedule. Before loading, it verifies that the file is correctly formatted and properly signed. The verification passes, because at that moment the file is the legitimate one. A brief interval separates verification from loading.

An attacker with limited access swaps the file inside that interval for one that keeps the same name and overall structure but adds an exception permitting traffic from an address they control, suppresses logging for connections matching that pattern, and opens ports that policy says stay closed. The firewall loads the tampered file without re-verifying it.

The organisation now has a firewall that reports a healthy configuration update while carrying an attacker-authored rule. The signature check was not defeated, it was simply applied to a file that stopped being the file that got loaded. The compromise persists until the next update cycle, and the monitoring that might have revealed it has been specifically disabled for the traffic that matters.

This is what makes TOCTOU a governance concern and not only a coding one. A control that verifies and then acts non-atomically provides assurance that is real at the moment of verification and worthless a moment later, while continuing to report success.

Where TOCTOU vulnerabilities tend to hide

Certain code is far likelier to carry this defect, and knowing where to look is more useful than knowing the definition:

  • Anything privileged that touches attacker-influenceable paths. Backup jobs, log rotators, installers, antivirus scanners and cleanup scripts are classic cases, because they run with high privilege over directories that lower-privileged users can write to.
  • Temporary file handling. Creating a file in a world-writable temporary directory by checking that a name is unused and then creating it is the textbook instance.
  • Access control decisions made in advance of use. Any system that authorises an operation and then performs it separately, including permission checks in cloud control planes, has the shape.
  • Legacy code written before the pattern was widely understood. The flaw predates most secure coding curricula, so older utilities carry it disproportionately.
  • Internal tooling that never went through security review. Custom scripts written to solve an operational problem tend to run with generous privileges and receive little scrutiny.

Assessments should ask for this explicitly. A vulnerability assessment scoped to known-CVE scanning will not find a TOCTOU flaw in bespoke code, because there is no signature to match. Threat modeling is a better fit, since the question it asks (who else can influence this resource, and when) is exactly the question the flaw turns on.

How to mitigate TOCTOU vulnerabilities

Mitigation advice for TOCTOU is frequently presented as a menu of equally weighted options. It is not. One approach removes the vulnerability and the rest reduce the probability of exploitation, and conflating the two is how organisations end up believing a flaw is fixed when it has only been made harder to hit.

The fix: make the check and the use one operation

The durable answer is atomicity. If the check and the use cannot be separated, there is no window to attack.

In file handling this normally means working with a handle rather than a name. A program opens the resource once, obtaining a file descriptor that refers to the object itself, and performs every subsequent check and operation against that descriptor. An attacker who repoints the filename afterwards achieves nothing, because the descriptor still refers to the file that was opened. Operating systems provide direct support for this: opening a file and then querying the descriptor, rather than querying the path and then opening it, inverts the vulnerable order. Options that refuse to follow symbolic links, and directory-relative operations that avoid re-resolving a whole path, close the remaining gaps.

The general principle transfers beyond files. Databases provide it through transactions and appropriate isolation levels, so a read and a dependent write commit as a unit. Distributed systems provide it through compare-and-swap operations, where the update carries the expected prior state and fails if reality has moved on.

Shortening the window is not the fix. Reducing the gap between check and use is worth doing, and it is often recommended first, but it changes an attacker’s success rate rather than their possibility of success. Since the attacker can retry indefinitely and only needs to succeed once, a narrower window buys time rather than safety. Re-checking immediately before use has the same weakness: it creates a smaller window, not no window.

Controls that limit and detect what remains

Not all vulnerable code can be rewritten, particularly in third-party or legacy systems, so the second layer assumes exploitation is possible and constrains it.

Least privilege is the highest-value control here, because TOCTOU exploitation is almost always the borrowing of someone else’s authority. A process restricted to the directories it genuinely needs can be tricked into far less than one running with full administrative rights. Running such processes under dedicated service accounts rather than root or SYSTEM converts a total compromise into a bounded one.

File integrity monitoring gives a detection path for the tampering variant, flagging unexpected changes to configuration and other sensitive files. Comprehensive logging of file access supports the investigation afterwards, though as the backup example showed, the logs will record a successful operation rather than an attack, so the analysis has to be looking for the right anomaly. Storing sensitive resources in directories that unprivileged users cannot write to removes the attacker’s ability to stage the swap in the first place, and is often the cheapest structural improvement available.

Governance that stops it coming back

The third layer addresses the fact that TOCTOU is a pattern developers reintroduce, not a one-time defect.

Secure coding standards should name the pattern and the approved alternative, so the guidance is actionable rather than a warning to be careful. Reviews should treat verify-then-act on any shared resource as a finding by default, which is a concrete thing to look for in a way that “check for race conditions” is not. Building this into the development lifecycle rather than bolting it on at the end is what makes it stick, and it is the point at which the fix is cheapest.

Testing needs realistic expectations. Static application security testing can flag known dangerous sequences, and the SAST tooling most teams already run will catch the textbook file-handling cases, though the guide on static application security testing explains why its view of interprocedural and timing-dependent behaviour is limited. Dynamic application security testing struggles differently: exercising a race requires provoking a timing window that may not open under normal test conditions. Misuse case testing is the better-matched technique, because it starts from what an attacker would attempt rather than from what the software is supposed to do.

Where these defences break down

Three limitations are worth stating plainly, because a guide that stops at the mitigation list overstates how solved this is.

Atomicity is not always available. Some operations genuinely cannot be made indivisible, particularly across system or network boundaries where a check happens in one component and the use in another. Distributed authorisation frequently has this shape, and the honest answer is compensating controls and a narrower blast radius rather than elimination.

Detection is weak by construction. The attack produces successful operations, not failures. Monitoring tuned to denials, errors and anomalous authentication sees nothing, which is why file integrity monitoring appears in the control list at all: it asks a different question.

Third-party code is largely out of reach. When the flaw is in a vendor product or a dependency, the options reduce to privilege restriction, isolation and vendor pressure. This is where the layered approach stops being defensive thoroughness and becomes the only available strategy.

Conclusion

TOCTOU is a small idea with a large blast radius. A program checks something, the answer stops being true, and the program acts anyway. The check was never wrong, which is what makes the flaw so durable: nothing in the system reports an error, no control is bypassed, and the logs record success.

For the CISSP, the recognisable shape matters more than the acronym. A scenario describing a privileged process that validates a resource and then operates on it separately, with an attacker able to influence that resource in between, is describing this flaw whether or not the words “time of check” appear. Questions in this area tend to reward two judgements in particular: that the durable fix is atomicity rather than a shorter window, and that least privilege limits the damage precisely because the attack works by borrowing privilege rather than defeating it.

Ready to test that under exam conditions? Our LSM CISSP practice tests are built around exactly these scenario questions: race conditions, secure coding failures, and the fine distinctions between a control that fails and a control that succeeds against the wrong object, with full explanations for every answer.

Quick reference for the CISSP exam

A TOCTOU vulnerability exists when a program checks a resource and then uses it as a separate operation, allowing the state to change in between. It is classified as CWE-367 and sits under CWE-362, the general race condition class.

The three-part structure

  • Time of check. The program validates the resource and receives an accurate answer.
  • The window. An interval of unbounded length in which the program is not observing the resource.
  • Time of use. The program acts on a decision that may no longer be valid.

The distinctions most likely to be tested

  • TOCTOU against race conditions generally. Every TOCTOU flaw is a race condition; most race conditions are not TOCTOU. TOCTOU is specifically the race between a validation and the action it authorised.
  • TOCTOU against memory safety flaws. A buffer overflow involves an invalid operation. In TOCTOU every operation is valid and every check is truthful, which is why static analysis detects overflows far more reliably.
  • Fixing against mitigating. Atomic operations remove the vulnerability. Shortening the window, retrying and re-checking before use reduce the probability of exploitation without removing it, because the attacker can retry and needs to win only once.
  • Whose privileges are used. The attacker does not gain privilege directly; they induce a privileged process to act for them, which is why least privilege bounds the impact so effectively.

Spotting the topic in a scenario

Look for a privileged process that validates something and then acts on it, a resource an attacker can influence between those steps, and an outcome in which the process did exactly what it was designed to do. Symbolic links, temporary files in shared directories, nightly automated jobs and configuration files verified before loading are the usual signals. If the scenario stresses that logs showed nothing unusual and no control was bypassed, that is a strong indication.

The mitigation hierarchy, in order

  1. Make the check and use atomic, typically by holding a file descriptor rather than re-resolving a name. This eliminates the flaw.
  2. Apply least privilege so a successful exploit reaches as little as possible.
  3. Monitor integrity of sensitive files, since the attack generates successful operations rather than errors.
  4. Govern the pattern through secure coding standards, targeted code review and misuse case testing, so it is not reintroduced.