//nefariousplan

TOCTOU That Isn't

A 'race condition' that's actually deterministic. Attacker controls timing because the other side hasn't run yet.

The CVE calls it a race condition. The advisory asks for "timing-sensitive mitigations." But there's no race. The attacker placed the resource before the privileged process started, or after it finished. Nobody timed anything.

Mechanism

A TOCTOU race requires both the attacker and the privileged process to be running, fighting for a resource over a narrow window. Mitigations focus on shrinking that window: atomic operations, file descriptors instead of paths, capability-based APIs. Many bugs filed as TOCTOU don't have that shape. The attacker's swap happened before the privileged code ran (the junction was placed at boot, the registry value set yesterday) or after it returned (the handle closed, the buffer freed, attacker writes into the gap cleanup left behind). No window to shrink. The attacker had minutes or days, not microseconds.

Variants under this umbrella all violate the race assumption differently:

Preemption. The resource was placed before the privileged code ran. Junction-preemption is the canonical case; pre-staged registry keys and DLL-plant directories are siblings. The attacker existed there first and waited.

Pre-existing handle. The attacker holds a file descriptor or kernel object obtained earlier. The privileged code's open is irrelevant because the attacker never let go of the original handle and continues to write through it.

Post-emption. Privileged code ran, returned, freed its handle. A temp file or shared buffer survived. Attacker writes into the gap before cleanup completes, or before the next consumer reads.

Stale snapshot. The check ran on a copy of state. The use ran on the live state. No race; the check was never going to be authoritative because it operated on the wrong object.

Each one wears the TOCTOU label. None is fixed by tighter atomics.

Exhibits

RedSun: How Windows Defender's Remediation Became a SYSTEM File Write. Defender's remediation is the "use" side of a TOCTOU framing, except the attacker already placed the quarantine path before Defender ran. Classic preemption: the race is deterministic because the other runner never had a chance to move first.

Boundaries

Not every TOCTOU is mislabeled. Real races exist. Concurrent processes fighting over open(2), two threads reading-modifying-writing the same state, kernel reentrancy on a shared structure. This pattern names the cases where the timing framing sends the fix in the wrong direction, not every bug that wears the TOCTOU label.

Not solved by atomicity primitives. fd-based APIs, O_NOFOLLOW, capability handles all shrink the race window. If there's no window, they don't help. Preemption needs directory ownership before any privileged code runs. Post-emption needs stricter cleanup guarantees after privileged code returns. Both demand a different shape of fix than a tighter atomic.

Defender playbook

When triaging a "TOCTOU" bug, ask when the attacker's controlled event happened. If it was before the privileged code started or after it ended, stop calling it a race and rescope the fix. The vocabulary leads the remediation; the wrong label ships the wrong patch.

Document the attacker's timing window in the advisory. A 30-day window is a different bug class than a 30-microsecond window. Exploitability, detection cost, defense-in-depth options all diverge. The mitigation section should reflect which class the bug is in, not copy boilerplate from the previous TOCTOU advisory.

Separate "you have time to patch" from "you don't" in user advisories. A 30-day attacker window is patchable on a normal cadence. A 30-microsecond window needs runtime mitigations or capability rearchitecture. Conflating the two under one CVE severity sends operations teams chasing the wrong fix and gives executives a false sense of which vulnerabilities are urgent.

Kinship

Junction Preemption. Junction-preemption is the cleanest concrete instance of this anti-pattern: an installer files a "race condition" CVE for a bug where the attacker's resource was placed at boot. The mitigation advice lands on the wrong axis until the timing framing is dropped.

A race needs two runners. If only one is running, you don't have a race. You have a handoff.