
TOCTOU Attacks Beat the Scanner by Design and Why Runtime Enforcement Stops Them
A TOCTOU attack passes the check, then swaps the resource before it is used. Scanners validate once and trust forever. Enforcement at the syscall is the only control that holds.
Reading Time: 5 minutes
TL;DR
- A TOCTOU (Time-of-Check to Time-of-Use) attack targets the gap between a check and the use that follows.
- In that window, an attacker swaps the resource for a malicious one.
- Anything that validates once and trusts afterward is bypassable by design. A scanner, an admission check, and a setuid program that calls access() then open() all share this flaw.
- The classic case is a symlink swap: a privileged program checks a file it is allowed to write, an attacker points that name at /etc/passwd, and the program overwrites the system password file.
- The fix is not a better check. It is enforcement at time-of-use, where the policy decision fires at the syscall the operation actually runs on.
- AccuKnox, built on the open-source KubeArmor engine, enforces through eBPF and Linux Security Modules whose hooks fire after the kernel resolves the real object, so the check and the use become the same event.
The Race, in One Concrete Example
TOCTOU is a race condition. A program checks a property of a resource, then acts on the result of that check. The bug exists because the two steps are not atomic: another process can run in between and change the property, so the second step operates on stale information. The Wikipedia entry on TOCTOU documents the pattern and its history.
The textbook example is a setuid program that wants to write a file on behalf of a real user:
if (access("file", W_OK) != 0) exit(1); // time of check
fd = open("file", O_WRONLY); // time of use
write(fd, data, len);
access() checks the real user’s permission, which is correct. Between that call and open(), an unprivileged attacker runs symlink(“/etc/passwd”, “file”). The check passed against a file the user could write. The open() now follows the symlink, and the privileged program overwrites /etc/passwd. The security check was real. The attacker bypassed the check because access() validated one file and open() used another.
The public record includes a 2019 root-access-to-host race in docker cp driven by a symlink swap, and a gateway compromise at Pwn2Own 2023, both listed in the same reference. Container filesystems, shared volumes, and CI workspaces are full of the mutable paths this attack needs.

How an eBPF program runs at a BPF-LSM hook inside the kernel, at the moment of the operation. Source: same article.
Why the Scanner and the Admission Gate Miss it
A vulnerability scanner reads an image, a manifest, or a filesystem and reports what it found at that instant. An admission controller checks a workload’s spec before it is scheduled. Both run at time-of-check. Neither watches what happens at time-of-use.
That is the structural problem. The scan of a container image is honest about the image it scanned, but the running container can mount a writable volume, resolve a symlink, or race a file open that the scan never saw.

A TOCTOU attack caught at runtime: the file changed between the check and the use. Source: Hunting TOCTOU and LD_PRELOAD attacks with eBPF-LSM, Medium.
Enforcement at Time-of-use, through eBPF and BPF-LSM
Linux Security Module (LSM) hooks are decision points inside the kernel that fire before a sensitive operation commits: opening a file, executing a program, loading a library. A security engineering write-up on hunting TOCTOU with eBPF LSM makes the key point: these hooks fire after the kernel has resolved the path, checked permissions, and validated the inode, so the hook sees the real kernel object, not the user-supplied argument an attacker can still swap.
When the policy runs at the file_open hook rather than at the userspace access() call, there is no window left to swap the resource, because the decision and the operation are the same event. The same write-up names the hooks that matter for this class: bprm_check_security for program execution, file_open for file and library access, and path_symlink and path_rename to catch rapid filesystem changes during an execution window.
AccuKnox uses exactly this layer. KubeArmor enforces policy through eBPF and BPF-LSM at the kernel, at the same privilege level as the operating system, with no userspace agent racing the attacker. Read the mechanics on how AccuKnox uses eBPF and BPF-LSM.

Kernel-enforced policy decisions in the AccuKnox console, applied at the operation itself rather than at an earlier check.
| Control | When it decides | Can an attacker swap the resource after? |
|---|---|---|
| Image or filesystem scanner | Time of check, on a snapshot | Yes, at runtime |
| Admission controller | Time of check, on the spec | Yes, after scheduling |
| Userspace access() guard | Time of check, on a path string | Yes, before open() |
| KubeArmor LSM enforcement | Time of use, on the resolved object | No, the decision is the operation |
What enforcement at time-of-use does not do
Runtime enforcement closes the check-versus-use gap on a workload under policy. It does not remove the underlying bug from your code, and a setuid binary with a TOCTOU flaw should still be fixed. Enforcement also depends on the LSM being active and the policy covering the sensitive paths, so a path you never restricted is a path the hook will allow.
A check that runs once and trusts forever is not a control against an attacker who owns the window after the check. Move the decision to the syscall, and the window disappears. A past check proves a resource was safe a moment ago. Enforcement at the syscall proves the resource is safe now.
Watch KubeArmor enforce policy at the kernel
KubeArmor is the open-source engine behind this enforcement model. This walkthrough covers getting started and three enforcement use cases.
FAQ
What does TOCTOU stand for?
Time-of-Check to Time-of-Use. It is a race where an attacker swaps a resource in the gap between a program checking it and using it.
Why can’t a scanner catch a TOCTOU attack?
A scanner reports the state it saw at check time. The swap happens later, at use time, so any control that validates once and trusts afterward is bypassable.
How does eBPF with BPF-LSM stop TOCTOU?
Its hooks fire in the kernel after the path and inode are resolved, at the moment the operation runs. The decision and the operation are the same event, so no swap window remains.
Does AccuKnox need a kernel module?
No. It enforces through eBPF and in-tree LSMs such as BPF-LSM and AppArmor. The same model works on Kubernetes, VMs, and bare metal.
Get a LIVE Tour
Ready For A Personalized Security Assessment?
“Choosing AccuKnox was driven by opensource KubeArmor’s novel use of eBPF and LSM technologies, delivering runtime security”

Golan Ben-Oni
Chief Information Officer
“At Prudent, we advocate for a comprehensive end-to-end methodology in application and cloud security. AccuKnox excelled in all areas in our in depth evaluation.”

Manoj Kern
CIO
“Tible is committed to delivering comprehensive security, compliance, and governance for all of its stakeholders.”

Merijn Boom
Managing Director




