Skip to content

upload_init creates an empty file before validating recipient, leaking orphans on bad input #125

@dobby-coder

Description

@dobby-coder

Summary

upload_init in src/main.rs creates a zero-byte file on disk before validating the request's recipient field. When the recipient is unparseable, the handler returns 400 Bad Request but the empty file in data_dir is never cleaned up. Each rejected request leaves a UUID-named empty file behind that the in-memory purge_task will not remove (it only walks Store::expirations, and no FileState was inserted for this UUID).

Code path

src/main.rs:91-139:

  1. File::create(Path::new(config.data_dir()).join(&uuid)) — file created on disk (line 101)
  2. bytes_to_hex(&rand::rng().random::<[u8; 32]>()) — token generated (line 109)
  3. request.recipient.parse() — recipient validated last (line 111)
  4. On Err, returns 400 — but the file from step 1 stays on disk

Store::create is never called on this path either, so the cleanup task has no record to drive a removal.

Impact

  • Disk fills with empty zero-byte files when clients (or attackers) repeatedly POST /fileupload/init with malformed recipients
  • No quota or rate limit on /fileupload/init — easily exploitable

Suggested fix

Reorder: parse the recipient first; only on success generate UUID, create the on-disk file, and call store.create. This matches the flow already used in upload_finalize for cleanup-on-error (tokio::fs::remove_file + store.remove).

let recipient = request.recipient.parse()
    .map_err(|e| Error::BadRequest(Some(format!("Could not parse e-mail address: {}", e))))?;

let uuid = uuid::Uuid::new_v4().hyphenated().to_string();
File::create(...).await.map_err(...)?;
// ...

Tests

Add a unit test that POSTs /fileupload/init with a malformed recipient and asserts the data_dir is unchanged afterwards.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions