Race Conditions and TOCTOU bugs

Web Advanced 📅 Published: 10/09/2025

Time-of-Check to Time-of-Use (TOCTOU) vulnerabilities are a class of race condition bugs that occur when there's a time gap between checking a reso...

Race Conditions and TOCTOU bugs

Time-of-Check to Time-of-Use (TOCTOU) vulnerabilities are a class of race condition bugs that occur when there's a time gap between checking a resource and using it, during which the resource can be modified by an attacker.

Understanding the Problem

TOCTOU vulnerabilities typically follow this pattern:

  1. Check - Application verifies a condition (file permissions, user rights, etc.)
  2. Time Gap - Brief period where attacker can modify the resource
  3. Use - Application acts based on the earlier check, now potentially invalid

Classic Example: File Operations

// VULNERABLE CODE
if (access("/tmp/file", W_OK) == 0) {  // Check: Can we write?
    // TIME GAP - Attacker can replace /tmp/file with symlink
    FILE *fp = fopen("/tmp/file", "w");  // Use: Write to file
    fprintf(fp, "sensitive data");
    fclose(fp);
}

Between the access() check and fopen() use, an attacker could replace the file with a symbolic link pointing to a sensitive system file.

Mitigation Strategies

  • Atomic operations - Use operations that check and act in one step
  • File descriptors - Keep file handles open to maintain consistency
  • Proper locking - Use filesystem locks or application-level synchronization
  • Avoid privileged operations - Drop privileges early when possible

Secure Alternative

// SECURE CODE
int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd != -1) {
    // File was created atomically, safe to use
    write(fd, "sensitive data", 14);
    close(fd);
}

Web Application Context

TOCTOU bugs also appear in web applications, particularly around:

  • Session validation and usage
  • Database constraint checks
  • File upload validation
  • Rate limiting implementations

The key to preventing TOCTOU vulnerabilities is to minimize or eliminate the time gap between check and use operations.