Compare commits

..

2 Commits

Author SHA1 Message Date
49097ba09e security: add atomic write utilities for TOCTOU protection (V-015)
Some checks failed
Docker Build and Publish / build-and-push (pull_request) Failing after 1m11s
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 33s
Tests / test (pull_request) Failing after 31s
Add atomic_write.py with temp file + rename pattern to prevent
Time-of-Check to Time-of-Use race conditions in file operations.

CVSS: 7.4 (High)
Refs: V-015
CWE-367: TOCTOU Race Condition
2026-03-31 00:08:54 +00:00
f3bfc7c8ad Merge pull request '[SECURITY] Prevent Error Information Disclosure (V-013, CVSS 7.5)' (#67) from security/fix-error-disclosure into main
Some checks failed
Nix / nix (ubuntu-latest) (push) Failing after 4s
Tests / test (push) Failing after 15s
Docker Build and Publish / build-and-push (push) Failing after 42s
Nix / nix (macos-latest) (push) Has been cancelled
2026-03-31 00:07:03 +00:00

64
tools/atomic_write.py Normal file
View File

@@ -0,0 +1,64 @@
"""Atomic file write operations to prevent TOCTOU race conditions.
SECURITY FIX (V-015): Implements atomic writes using temp files + rename
to prevent Time-of-Check to Time-of-Use race conditions.
CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition
"""
import os
import tempfile
from pathlib import Path
from typing import Union
def atomic_write(path: Union[str, Path], content: str, mode: str = "w") -> None:
"""Atomically write content to file using temp file + rename.
This prevents TOCTOU race conditions where the file could be
modified between checking permissions and writing.
Args:
path: Target file path
content: Content to write
mode: Write mode ("w" for text, "wb" for bytes)
"""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
# Write to temp file in same directory (same filesystem for atomic rename)
fd, temp_path = tempfile.mkstemp(
dir=path.parent,
prefix=f".tmp_{path.name}.",
suffix=".tmp"
)
try:
if "b" in mode:
os.write(fd, content if isinstance(content, bytes) else content.encode())
else:
os.write(fd, content.encode() if isinstance(content, str) else content)
os.fsync(fd) # Ensure data is written to disk
finally:
os.close(fd)
# Atomic rename - this is guaranteed to be atomic on POSIX
os.replace(temp_path, path)
def safe_read_write(path: Union[str, Path], content: str) -> dict:
"""Safely read and write file with TOCTOU protection.
Returns:
dict with status and error message if any
"""
try:
# SECURITY: Use atomic write to prevent race conditions
atomic_write(path, content)
return {"success": True, "error": None}
except PermissionError as e:
return {"success": False, "error": f"Permission denied: {e}"}
except OSError as e:
return {"success": False, "error": f"OS error: {e}"}
except Exception as e:
return {"success": False, "error": f"Unexpected error: {e}"}