find-race-conditions

star 79

Detects race conditions in PHP code. Finds shared mutable state, check-then-act patterns, TOCTOU vulnerabilities, concurrent modification issues.

dykyi-roman By dykyi-roman schedule Updated 2/16/2026

name: find-race-conditions description: Detects race conditions in PHP code. Finds shared mutable state, check-then-act patterns, TOCTOU vulnerabilities, concurrent modification issues.

Race Condition Detection

Analyze PHP code for concurrency issues and race conditions.

Detection Patterns

1. Check-Then-Act (TOCTOU)

// BUG: Time-of-check to time-of-use
if (file_exists($path)) {
    $content = file_get_contents($path); // File may be deleted
}

// BUG: Check then modify
if (!$user->hasOrder()) {
    $order = new Order();
    $user->addOrder($order); // Another request may add order
}

// BUG: Inventory check-then-act
if ($product->getStock() >= $quantity) {
    $product->decreaseStock($quantity); // Race with other orders
}

2. Shared Mutable State

// BUG: Static mutable property
class Counter {
    private static int $count = 0;

    public function increment(): void {
        self::$count++; // Not atomic
    }
}

// BUG: Shared cache without locking
class Cache {
    private array $data = [];

    public function getOrSet(string $key, callable $factory): mixed {
        if (!isset($this->data[$key])) {
            $this->data[$key] = $factory(); // May compute twice
        }
        return $this->data[$key];
    }
}

3. Read-Modify-Write Without Lock

// BUG: Non-atomic increment
$counter = $redis->get('counter');
$redis->set('counter', $counter + 1); // Lost update

// BUG: Balance update
$balance = $account->getBalance();
$account->setBalance($balance - $amount); // Race condition

// FIXED: Use atomic operations
$redis->incr('counter');

4. File System Race Conditions

// BUG: Directory creation race
if (!is_dir($path)) {
    mkdir($path); // Another process may create it
}

// BUG: File write race
$data = json_decode(file_get_contents($file));
$data['count']++;
file_put_contents($file, json_encode($data)); // Lost update

5. Database Race Conditions

// BUG: No optimistic locking
$entity = $repository->find($id);
$entity->setStatus('processed');
$entityManager->flush(); // Another process may have changed it

// BUG: Unique constraint race
if (!$repository->findByEmail($email)) {
    $user = new User($email);
    $entityManager->persist($user); // Duplicate may be created
}

6. Session Race Conditions

// BUG: Session data race
$cart = $_SESSION['cart'];
$cart[] = $newItem;
$_SESSION['cart'] = $cart; // Lost update with concurrent requests

Grep Patterns

# Check-then-act patterns
Grep: "if\s*\(file_exists\([^)]+\)\)\s*\{[^}]*file_get_contents" --glob "**/*.php"

# Static mutable properties
Grep: "private static\s+(?!readonly)" --glob "**/*.php"

# Read-modify-write on Redis
Grep: "->get\([^)]+\)[^;]*\+[^;]*->set" --glob "**/*.php"

# Non-atomic increment
Grep: "\+\+|\-\-|self::\$\w+\s*\+=" --glob "**/*.php"

Severity Classification

Pattern Severity
Financial data race ๐Ÿ”ด Critical
Inventory TOCTOU ๐Ÿ”ด Critical
Unique constraint race ๐ŸŸ  Major
File system race ๐ŸŸ  Major
Cache stampede ๐ŸŸก Minor
Counter race ๐ŸŸก Minor

Fixes

Use Locks

// Database lock
$connection->beginTransaction();
$entity = $repository->find($id, LockMode::PESSIMISTIC_WRITE);
$entity->process();
$connection->commit();

Use Atomic Operations

// Redis atomic increment
$redis->incr('counter');

// Database atomic update
$connection->executeStatement(
    'UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?',
    [$quantity, $productId, $quantity]
);

Use Optimistic Locking

#[Version]
private int $version;

// Will throw OptimisticLockException on conflict

Output Format

### Race Condition: [Description]

**Severity:** ๐Ÿ”ด/๐ŸŸ /๐ŸŸก
**Location:** `file.php:line`
**Type:** [TOCTOU|Shared State|Read-Modify-Write|...]

**Issue:**
[Description of the race condition]

**Code:**
```php
// Problematic code

Fix:

// Thread-safe version

Install via CLI
npx skills add https://github.com/dykyi-roman/awesome-claude-code --skill find-race-conditions
Repository Details
star Stars 79
call_split Forks 18
navigation Branch main
article Path SKILL.md
More from Creator