TOCTOU (Filesystem)

Time-of-check / time-of-use race condition class where a security check and the subsequent filesystem operation are not atomic, allowing an attacker to swap the resolution target between the two steps and bypass the check.

TOCTOU (Filesystem) — time-of-check / time-of-use race condition — is a class of attack where a security check and the subsequent filesystem operation are not atomic, allowing an attacker to swap the resolution target between the two steps. The application sees a safe path at check time; the kernel operates on a different (unsafe) path at use time, because something happened in between.

The classical pattern: an MCP server validates that a path is inside the configured root, finds it safe, then opens the file. Between the validation and the open, an attacker who has write access to the relevant directory replaces the path with a symbolic link pointing outside the root. The open operates on the new target. The check passed; the operation went somewhere else.

TOCTOU compounds symlink-following attacks and path-prefix bypasses. Even an application that resolves the path correctly at validation time can be defeated by a TOCTOU race that swaps the target before use. This is why every well-engineered filesystem-validation pattern eventually concludes that application-layer checks are not enough — the only structural fix is atomic check-and-operate primitives that guarantee the kernel's resolution at use time matches the resolution that was checked.

Why TOCTOU Is Hard to Defend

Three properties make TOCTOU hard to defend in application code. The race window can be tiny but reliable. Modern attackers can win race windows of single-digit microseconds with appropriate setup. The race window does not need to be small. If the application validates a path then waits for the agent's reasoning step before opening, the window can be hundreds of milliseconds. The validation primitive does not extend to use. The application has no way to say "open the file I just validated, even if a concurrent process changes what that path resolves to." The kernel's open re-resolves the path independently.

Defensive Patterns

The structurally correct defence is atomic check-and-operate primitives that the kernel itself guarantees. On Linux, openat2 with RESOLVE_BENEATH performs the open as a single atomic operation that fails if resolution would escape the configured root — there is no race window because no separate check exists. File-handle-based APIs (open the directory once, perform all subsequent operations relative to the directory file descriptor) avoid path re-resolution entirely.

Where atomic primitives are not available, the operational fallback is to remove the attacker's write access to the directory entirely — making it impossible to create the symlink that the race would exploit. For MCP servers running with the developer's UID, this is rarely feasible; the developer's own writes can race the agent's operations even without explicit attacker action.

For deeper guidance, see the EscapeRoute case study and the MCP Security Audit service description.

Need expert guidance on TOCTOU (Filesystem)?

Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.

Get a Quote