Skip to content

[BUG] Temp file leak in validate_upload when validation fails partway through #744

Description

@vipul674

Description of the Bug

In backend/app/routes/documents.py, the validate_upload function creates a temporary file at the start of validation:

temp_path = str(upload_dir / f"{uuid.uuid4()}{ext}")
with open(temp_path, "wb") as temp_file:
    shutil.copyfileobj(file.file, temp_file)

If validation fails after the file is written but before the success path returns it, the temp file should be cleaned up. The cleanup code does handle common failure paths, but there are edge cases:

  1. If shutil.copyfileobj() succeeds but Path(temp_path).stat().st_size raises a filesystem error, the temp file is leaked
  2. If an unexpected exception occurs between file creation and the validation check, the finally block does not clean up (it's intentionally a no-op since caller manages the file)
  3. The try/finally in the calling function (upload_document) only cleans up on error if the temp path was successfully returned, but on some exception paths the temp_path is never returned and never cleaned up

This causes disk space accumulation over time, especially with repeated failed uploads.

Steps to Reproduce

  1. Trigger a filesystem error while Path(temp_path).stat().st_size is executing (e.g., by removing the directory concurrently)
  2. The exception propagates without cleaning up the temp file
  3. The temp file remains on disk permanently

Expected Behavior

Temp files should be cleaned up on ALL failure paths, not just the expected ones. A robust pattern is:

temp_path = None
try:
    temp_path = str(upload_dir / f"{uuid.uuid4()}{ext}")
    # ... validation logic ...
    return temp_path
except Exception:
    if temp_path and Path(temp_path).exists():
        Path(temp_path).unlink()
    raise

Affected File

backend/app/routes/documents.py (lines ~107-149)

Suggested Fix

Add a comprehensive cleanup in the except block to delete the temp file on any failure. Only the caller should receive the path on success.

GSSoC '26

  • Yes, I am participating in GirlScript Summer of Code and would like to fix this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gssocGirlScript Summer of Code 2026 issue/PR

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions