---
title: one extension away
description: >-
  a short update on a media path bug i found in zapfast, and why i review
  third party clients before using them
published: 2026-10-10T00:00:00.000Z
updated: 2026-10-10T00:00:00.000Z
tags:
  - security
  - disclosure
  - whatsapp
draft: false
signature: ./zapfast-path-traversal.md.asc
---

i found a path traversal in [zapfast](https://github.com/crmne/zapfast), a native whatsapp client by [carmine](https://x.com/paolino). on windows, a file someone sends you could get saved outside of the media cache folder it's supposed to stay in

it's fixed now, and carmine handled the report very fast and responsibly (seriously, i've never been replied to so fast before). this is a short update on what i found, and why i'd rather not use a custom client for anything before doing an independent review of it

it all started on sep 19th at one in the morning, when i saw a tweet by carmine about zapfast:

```twitter
zapfast/september-16
```

so i installed it on my [fedora kinoite](https://fedoraproject.org/atomic-desktops/kinoite/) setup as a [flatpak](https://flatpak.org/). overall i liked the app despite it being a bit underpolished, but i thought it was exciting that someone even dared to remake something natively

the future looks even more exciting, because the cost of native development has sunk so much. everyone is suddenly returning to native (eg shopify's [back to native](https://shopify.engineering/back-to-native) post)

but it works both ways. with the cost sunk this much, it's now trivial to slop out a bunch of code and ship it. and when you're working on something that has direct access to all of your data, every chat, every contact, every file someone sends you, you cannot be careless like that

that's why i wouldn't use a third party client without checking it first. you're handing it your whole account and just trusting that someone actually read what got generated

zapfast is open source though, which i really like. whatever slop you're making, keeping it in the open makes it much easier to audit, and the community can help you make it less slop

so around 3am i thought, since it looks a bit underpolished, does the same apply to the inside? i cloned upstream to my dev folder and started looking

naturally the most vulnerable paths are usually the paths. no but seriously, i went almost straight for them: how it handles messages, sticker imports and the media download path. in [`worker.rs`](https://github.com/crmne/zapfast/blob/main/src/backend/worker.rs) i noticed something funny about the mime extension handling

it was technically sound and worked fine on linux & macos, but on windows a mime type like `application/octet-stream\..\..\…\Startup\x.lnk` would walk right out of the media cache. windows treats `\` as a path separator so `\..\` walks up a folder, while on linux & macos it's just a regular character in a file name. despite `sanitize()`'ing the file name it was appending the ending as is afterwards, and the mime type is essentially attacker controlled. and since zapfast downloads incoming files on its own, this, combined with writing a file to the windows' startup folder, can get you a zero-click, arbitrary code execution (on the next system start)

you can't really send a file with such an extension using the client, so i used [whatsapp-rust](https://github.com/oxidezap/whatsapp-rust), the library zapfast is built on. a few hours later i already had a working poc that would send such a file to anyone. i recorded it in my vm, packaged the poc with the video and sent it over by 7am (i dont sleep at night lol)

```video
zapfast-poc-v2.mp4
```

funny thing, i first sent everything as email attachments. only after an hour did i notice that gmail had flagged all of them as malware and stripped them out, so i had to panic-send a new email with a [proton drive](https://pr.tn/ref/D36104JV) (referral link) instead. i'll be using that from now on

just 3 days later carmine replied and said the fix was already in upstream

```email
zapfast/the-fix
```

two days after that it was [released](https://github.com/crmne/zapfast/releases/tag/v0.16.0) in 0.16.0. its a shame there's no advisory for it though, so i didnt get a credit or anything (also why dont we even have advisories enabled on a repo where it's literally critical to have them?)

anyways, as promised, this is just a short update to not let the blog die. as always, review the stuff you're using, and be careful out there!
