no-toctou-vulnerability
Detects Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerabilities in file system operations.
Keywords: TOCTOU, time-of-check, time-of-use, race condition, security, ESLint rule, CWE-367
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Error |
| CWE | CWE-367 |
| OWASP | A01:2021 |
| Auto-Fix | ❌ No |
| Suggestions | ✅ 3 available |
| Category | Security |
Vulnerability and Risk
Vulnerability: A Time-of-Check to Time-of-Use (TOCTOU) vulnerability relies on the timing window between checking a condition (e.g., "does this file exist?") and using the result (e.g., "read the file").
Risk: An attacker can alter the state of the system (e.g., delete or replace the file with a symbolic link) during this window, causing the application to perform actions on the wrong resource. This can lead to privilege escalation, data corruption, or denial of service.
Rule Details
TOCTOU vulnerabilities occur when a program checks a condition (like file existence) and later performs an action based on that check, but the condition may have changed between the check and the action.
Why This Matters
| Issue | Impact | Solution |
|---|---|---|
| 🔒 Race Condition | Attackers can exploit timing window | Use atomic operations |
| 🐛 Data Integrity | File state may change unexpectedly | Use fs.promises API |
| ⚡ Reliability | Operations may fail or produce wrong results | Handle errors properly |
Configuration
interface Options {
/** Ignore in test files. Default: true */
ignoreInTests?: boolean;
/** File system methods to check. Default: ['fs.existsSync', 'fs.statSync', 'fs.accessSync'] */
fsMethods?: string[];
}Examples
❌ Incorrect
// TOCTOU vulnerability: file state can change between check and use
if (fs.existsSync('config.json')) {
const data = fs.readFileSync('config.json'); // ⚠️ File may no longer exist
}
// Stat-then-use pattern
const stats = fs.statSync('file.txt');
if (stats.isFile()) {
fs.unlinkSync('file.txt'); // ⚠️ File may have changed
}✅ Correct
// Use try-catch with fs.promises (atomic behavior)
try {
const data = await fs.promises.readFile('config.json');
// Process data
} catch (err) {
if (err.code === 'ENOENT') {
// File doesn't exist - handle appropriately
}
}
// Use proper locking for concurrent access
import { lock } from 'proper-lockfile';
const release = await lock('file.txt');
try {
const data = await fs.promises.readFile('file.txt');
await fs.promises.writeFile('file.txt', modifiedData);
} finally {
await release();
}Configuration Examples
Basic Usage
// eslint.config.mjs
export default [
{
rules: {
'node-security/no-toctou-vulnerability': 'error',
},
},
];Custom Configuration
// eslint.config.mjs
export default [
{
rules: {
'node-security/no-toctou-vulnerability': [
'error',
{
ignoreInTests: true,
fsMethods: ['fs.existsSync', 'fs.statSync', 'fs.accessSync'],
},
],
},
},
];LLM-Optimized Output
🔒 CWE-367 OWASP:A01-Broken-Access-Control CVSS:7.0 | TOCTOU vulnerability | HIGH
Fix: Use atomic operations or fs.promises for file operations | https://cwe.mitre.org/data/definitions/367.htmlSuggestions
When this rule reports an error, it provides three suggestions:
- Use Atomic Operations - Use atomic file operations like
fs.promises.access()thenfs.promises.readFile() - Use fs.promises - Use the Promise-based fs API for better error handling
- Add Proper Locking - Use a file locking library like
proper-lockfilefor concurrent access
Related Rules
detect-non-literal-fs-filename- Detects path traversalno-zip-slip- Prevents zip slip vulnerabilities
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Values from Variables
Why: Values stored in variables are not traced.
// ❌ NOT DETECTED - Value from variable
const value = userInput;
dangerousOperation(value);Mitigation: Validate all user inputs.
Wrapper Functions
Why: Custom wrappers not recognized.
// ❌ NOT DETECTED - Wrapper
myWrapper(userInput); // Uses dangerous API internallyMitigation: Apply rule to wrapper implementations.
Dynamic Invocation
Why: Dynamic calls not analyzed.
// ❌ NOT DETECTED - Dynamic
obj[method](userInput);Mitigation: Avoid dynamic method invocation.
Further Reading
- CWE-367: TOCTOU Race Condition - Official CWE documentation
- OWASP TOCTOU - OWASP vulnerability documentation
- Node.js fs.promises - Recommended async file API