Patch, then patch again: how CVE-2026-28289 turned FreeScout's fix into zero-click RCE
A zero-width space undid CVE-2026-27636's 1.8.206 fix in six days — and escalated it to unauthenticated RCE via email. Fixed in 1.8.207.

On February 25, 2026, FreeScout shipped version 1.8.206 to close an authenticated remote-code-execution bug, CVE-2026-27636. Six days later, researchers at OX Security showed the fix was bypassable — and escalated the same root flaw to a zero-click, unauthenticated RCE now tracked as CVE-2026-28289. It is a clean, small, almost textbook example of why a patch is a milestone, not a finish line.
Scores as of 2026-07-18live record →
What FreeScout is, and why a helpdesk bug travels
FreeScout is a self-hosted help desk and shared mailbox built on PHP's Laravel framework — a popular subscription-free alternative to Help Scout. Per OX Research's March 2026 writeup, Shodan surfaced roughly 1,100 internet-exposed instances across public-health institutions, technology providers, financial services, and news organizations. A helpdesk sits on top of sensitive support tickets and inbound mail, which is exactly why an RCE here lands hard.
The first fix: CVE-2026-27636
CVE-2026-27636 (CVSS 8.8) let an authenticated user with upload permission write a .htaccess or .user.ini file on Apache servers configured with AllowOverride All — a common default — and use it to redefine how files in that directory execute, reaching RCE. The 1.8.206 fix appended an underscore to any uploaded filename that used a restricted extension or began with a dot, so .htaccess became _htaccess. Reasonable. Not enough.
The bypass: one zero-width space
OX found that prepending a zero-width space (Unicode U+200B) to the filename slips it past the dot-prefix check, because the invisible character is not the literal . the check looks for. The check runs before sanitizeUploadedFileName() strips invisible characters — a textbook time-of-check / time-of-use (TOCTOU) ordering bug. After sanitization the U+200B is removed, and the file lands on disk as a true .htaccess — exactly what the check was meant to block.
Why the 1.8.206 check missed it: check-before-sanitize (TOCTOU)
- Attacker uploads: U+200B + .htaccess
- Check: does name start with a dot?
- Yes → underscore appended → blocked
- No — U+200B hides the leading dot
- Validation passes
- sanitizeUploadedFileName() strips U+200B
- File saved to disk as true .htaccess
- Apache honours it → remote code execution
From authenticated to zero-click (Mail2Shell)
OX then went further. A crafted email sent to any mailbox FreeScout is configured to receive needs no authentication and no user interaction; its attachment is written to a predictable path under /storage/attachment/, which is web-accessible. That turns the authenticated upload chain into a zero-click unauthenticated RCE — the path the CVE-2026-28289 CVSS vector (AV:N/AC:L/PR:N/UI:N/S:C) actually scores. OX calls the technique Mail2Shell.
| Label | Value |
|---|---|
| CVE-2026-27636 (original) | 2.12 |
| CVE-2026-27637 (companion) | 0.67 |
| CVE-2026-28289 (bypass) | 31.14 |
Original vs bypass
CVE-2026-27636 vs CVE-2026-28289
| CVE-2026-27636 — the original | CVE-2026-28289 — the bypass | |
|---|---|---|
| CVSS | 8.8 High | 10.0 Critical |
| Privileges required | Low (auth + upload) | None (per CVSS vector) |
| Scope | Unchanged | Changed |
| EPSS | 0.021 (79th pct) | 0.311 (98th pct) |
| Fixed in | 1.8.206 | 1.8.207 |
| Public PoC | No | Yes |
What the CVSS 10 actually measures (and what it doesn't)
Disclosure timeline
FreeScout .htaccess RCE — from first fix to bypass
- Original flaws disclosedFreeScout 1.8.206 ships fixes for CVE-2026-27636 (.htaccess upload RCE) and CVE-2026-27637 (predictable auth token). Original reporter: Offensive.sa (per OX).
- Bypass found and shipped same dayOX Research publishes a filename-validation bypass — now CVE-2026-28289 — that defeats the 1.8.206 dot-prefix check with a zero-width space, and escalates it to zero-click unauthenticated RCE via email (Mail2Shell). FreeScout 1.8.207 released the same day.
- Exploit catalogedPublic advisory (GHSA-5gpc-65p8-ffwp) and the OX writeup with a proof-of-concept video are indexed in exploit catalogs.
- Current posture (this article)Fixed in 1.8.207. EPSS in the 98th percentile, a public PoC exists, but the flaw is not yet in CISA KEV per our data.
What to do right now
- Upgrade FreeScout to 1.8.207 or later. Version 1.8.206 is not sufficient — the dot-prefix check it added is bypassable.
- On Apache, set
AllowOverride Nonefor the FreeScout document root, even on 1.8.207. This is standing hardening, not just a workaround. - Hunt for indicators of prior exploitation: search
storage/attachmentfor rogue.htaccessor.user.inifiles. - Rotate the Laravel
APP_KEYif you ever ran an affected version with internet exposure — CVE-2026-27637 made a leaked key sufficient for admin takeover. - Subscribe this product to version-triggered CVE alerts so the next bypass reaches you before it reaches attackers.
$ find /var/www/freescout/storage/attachment \$ \( -name '.htaccess' -o -name '.user.ini' \) -type f -print$ # Anything printed here is suspicious — uploaded dotfiles should not exist$ # in attachment storage. Review and remove, then check access logs.# /etc/apache2/sites-available/freescout.conf — defence in depth
<Directory /var/www/freescout/public>
AllowOverride None
Require all granted
</Directory>
# Apply: a2ensite freescout && systemctl reload apache2We run FreeScout on nginx. Are we affected?
.htaccess RCE vector is Apache-specific — nginx ignores .htaccess. But the underlying upload-validation flaw still lets an attacker write attacker-controlled files into web-accessible storage, so treat 1.8.207 as required regardless of web server.We applied 1.8.206 when CVE-2026-27636 came out. Are we done?
Is CVE-2026-28289 in CISA's KEV catalog?
Why is the CVSS 10.0 if the advisory says it needs authentication?
PR:N/UI:N) reflects OX Research's escalation to an unauthenticated, zero-click path via a crafted email to a configured mailbox. The NVD advisory prose scopes the core flaw to authenticated users with upload permission. Both preconditions matter for triage — and both are closed by 1.8.207.Data as of 2026-07-18live record →