File transfer security
Last updated: 2026-06-05
This page explains, transparently, how Dropfleet protects your files and which libraries provide that protection. It is informational and complements the Terms of Service and the Privacy Policy (both in French).
In short
- Two modes chosen when you send: Standard (the server holds the bytes, which makes antivirus scanning possible) and Confidential — zero-knowledge (end-to-end encryption: the server never sees your files in the clear).
- Encryption in transit everywhere (HTTPS/TLS).
- Automatic deletion at the chosen expiry or once the download limit is reached.
- No third-party scripts (ads, analytics) are loaded on pages that carry a decryption key.
- Opaque, unguessable identifiers: a link cannot be guessed.
The transfer, step by step
- Preparation (browser). In Confidential mode your files are encrypted on your device before anything is sent. In Standard mode they are sent as-is to storage.
- Direct upload. The browser uploads the bytes directly to object storage via short-lived presigned URLs — the application never relays the bytes itself.
- Storage. The bytes live in object storage (Garage) on a disk encrypted at rest (LUKS). In Confidential mode they are already end-to-end encrypted.
- Scanning (Standard mode). An antivirus scans the files before they become downloadable (see "Antivirus").
- Download & decryption. The recipient fetches the bytes via a presigned URL; in Confidential mode, decryption happens in their browser.
Confidential mode (zero-knowledge)
In Confidential mode a master key is generated randomly in your browser and placed in the
URL fragment (the part after the # of the share link). Browsers never send that fragment to
the server, so the key stays with you and with whoever you give the link to.
The direct consequence: the operator cannot read your files in this mode — but anyone holding
the full link (including the #) can decrypt them. Share the link over a trusted channel.
Technical details
End-to-end encryption (Confidential mode)
| Item | Detail |
|---|---|
| Library | libsodium (libsodium-wrappers-sumo 0.8.4), bundled into the application (no external CDN) |
| Content encryption | XChaCha20-Poly1305 in secretstream mode, in 64 KiB chunks, with a final marker (anti-truncation: a truncated stream is rejected) |
| Master key | 256-bit, generated by a cryptographic RNG (CSPRNG, randombytes_buf), carried as base64url in the # |
| Per-file subkeys | derived with BLAKE2b — every file has its own key |
| File names & types | encrypted separately with crypto_secretbox (XSalsa20-Poly1305) — the server never sees the real names |
| Authentication & integrity | every chunk carries a Poly1305 tag: any tampering or truncation is detected on decryption |
Multi-file archives are zipped with fflate, which has no cryptographic role — decryption always precedes archiving.
Transfer passwords
An optional password can lock a transfer. It is hashed with Argon2id (OWASP parameters: 19 MiB memory, 2 iterations, parallelism 1, 16-byte random salt), in PHC format, and verified in constant time. The password is a server-side lock: in Confidential mode it does not replace the decryption key.
In transit & at rest
- In transit: everything goes over HTTPS/TLS; the HSTS header forces HTTPS in browsers.
- At rest: the object-storage volume is encrypted at the disk level (LUKS). There is no application-layer server-side encryption in Standard mode — which is why Confidential mode exists for sensitive content.
Antivirus
In Standard mode, all files are scanned by ClamAV before they become downloadable, regardless of size. For very large files the scan can take time: the recipient sees a "scan in progress" state, and the download is unlocked only once a clean scan completes; a file flagged as infected is deleted. In Confidential mode, because files are end-to-end encrypted, they cannot be scanned server-side.
Lifecycle & isolation
- Expiry & auto-deletion: each transfer is deleted at expiry or once the download limit is reached (purge worker + database TTL index).
- Opaque identifiers: transfer identifiers use 128 bits of randomness — not enumerable.
- Security headers: a strict CSP that allows no third-party scripts
(
script-src 'self' 'wasm-unsafe-eval'),X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy: no-referrer(the link and its#do not leak via the referrer),Cross-Origin-Opener-Policy,Permissions-Policy. - Rate limiting per IP address and per-transfer lockout of password attempts.
Libraries and components
| Component | Version | Role |
|---|---|---|
| libsodium-wrappers-sumo | 0.8.4 | end-to-end encryption (browser) |
| fflate | 0.8.x | browser-side ZIP archiving (non-cryptographic) |
Argon2id (golang.org/x/crypto) |
— | hashing of transfer passwords |
| ClamAV | 1.4 | antivirus scanning (Standard mode) |
| Garage | v2 | S3-compatible object storage (encrypted at rest via LUKS) |
| MongoDB / Valkey | — | metadata (TTL expiry) / sessions & rate limiting |
| Caddy / Traefik | — | TLS termination, security headers |
What this security does not cover (transparency)
- The link is the key. In Confidential mode, anyone who obtains the full link (with the
#) can decrypt the content. A link can leak (clipboard, browser history, message link previews). Share it over a trusted channel. - Metadata is not end-to-end encrypted. The approximate size, the number of files, any email addresses provided and the accompanying message are not protected by end-to-end encryption.
- Password ≠ E2E key. The password is a server-side access control; it does not encrypt the content.
- Trust in the served code. As with any end-to-end encryption delivered through a browser, confidentiality assumes the integrity of the code we serve (HTML/JavaScript). We bundle our libraries (no third-party CDN) and enforce a strict CSP, but this limitation is inherent to web-delivered E2E.
- A file is unscanned until scanning finishes. A very large Standard-mode file is only downloadable once its antivirus scan has completed.
Reporting & contact
To report illegal content, see Reporting & takedown (DSA / DMCA). For questions about personal data, see the Privacy Policy.