From 49097ba09e2af20e13c7355957da64430c0b1b16 Mon Sep 17 00:00:00 2001 From: Allegro Date: Tue, 31 Mar 2026 00:08:54 +0000 Subject: [PATCH] security: add atomic write utilities for TOCTOU protection (V-015) 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 --- tools/atomic_write.py | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 tools/atomic_write.py diff --git a/tools/atomic_write.py b/tools/atomic_write.py new file mode 100644 index 000000000..44c24fc5a --- /dev/null +++ b/tools/atomic_write.py @@ -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}"}