toctou-runtime-enforcement-ebpf-lsm

TOCTOU Attacks Beat the Scanner by Design and Why Runtime Enforcement Stops Them

 |  Edited : September 07, 2026

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.

toctou runtime enforcement ebpf lsm 2c

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.

TOCTOU attack - figure 2

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.

TOCTOU attack - figure 3

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.

Ready For A Personalized Security Assessment?

“Choosing AccuKnox was driven by opensource KubeArmor’s novel use of eBPF and LSM technologies, delivering runtime security”

idt

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.”

prudent

Manoj Kern

CIO

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

tible

Merijn Boom

Managing Director

×