CVE-2026-40565 Overview
CVE-2026-40565 is a stored cross-site scripting (XSS) vulnerability [CWE-79] in FreeScout, a free self-hosted help desk and shared mailbox application. The flaw resides in the linkify() function within app/Misc/Helper.php. Versions prior to 1.8.213 convert plain-text URLs in email bodies into HTML anchor tags without escaping double-quote characters. An attacker who sends a crafted email containing a URL with embedded " characters can break out of the href attribute and inject arbitrary HTML attributes. Version 1.8.213 resolves the issue by applying htmlspecialchars() to both the link target and link text.
Critical Impact
Remote attackers can deliver malicious payloads through email content that execute in the browser of FreeScout agents viewing the conversation, enabling session theft and UI redress.
Affected Products
- FreeScout versions prior to 1.8.213
- Self-hosted FreeScout help desk deployments
- FreeScout shared mailbox installations using default HTML email rendering
Discovery Timeline
- 2026-04-21 - CVE-2026-40565 published to NVD
- 2026-04-22 - Last updated in NVD database
Technical Details for CVE-2026-40565
Vulnerability Analysis
The vulnerability is a stored XSS that arises from a sanitization ordering flaw in FreeScout's email rendering pipeline. FreeScout calls getCleanBody() first, which invokes HTMLPurifier to sanitize the incoming email body. HTMLPurifier correctly preserves literal " characters inside text nodes since they are valid text content. After purification, linkify() performs a regex-driven transformation that wraps any plain-text URL in an <a href="..."> tag using unescaped string concatenation.
Because the URL captured from the email body is interpolated directly into the href attribute, a URL containing a " character closes the attribute prematurely. The remainder of the URL is then parsed by the browser as additional HTML attributes, allowing event handlers such as onmouseover or onclick to be injected. The injected markup is stored in the conversation and re-rendered to every agent viewing the ticket.
Root Cause
The root cause is missing output encoding during HTML construction. The legacy linkify() implementation built anchor tags through raw string interpolation without applying htmlspecialchars() to either the href value or the visible link text. HTMLPurifier was bypassed because the dangerous markup was synthesized after purification, not before.
Attack Vector
An unauthenticated attacker sends an email to a FreeScout-monitored mailbox. The email body contains a URL crafted with embedded double quotes and additional HTML attributes. When an agent opens the conversation, the injected attributes execute in the agent's authenticated session context, enabling cookie exfiltration, CSRF actions, or phishing overlays. User interaction is required to view the ticket.
$link = $match[2];
$link = substr($link, strlen($match[3]));
//return '<' . array_push($links, "<a $attr href=\"$protocol://$link\">$protocol://$link</a>") . '>';
- return $match[1].'<' . array_push($links, "<a $attr href=\"$protocol://$link\">".$match[2]."</a>") . '>';
+ $href = htmlspecialchars($protocol.'://'.$link, ENT_QUOTES, 'UTF-8');
+ $link_text = htmlspecialchars($match[2], ENT_QUOTES, 'UTF-8');
+ return $match[1].'<' . array_push($links, "<a $attr href=\"".$href."\">".$link_text."</a>") . '>';
}, $value) ?: $value;
break;
case 'mail':
$value = preg_replace_callback('~([^\s<>]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:\)])~', function ($match) use (&$links, $attr) {
- return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\">{$match[1]}</a>") . '>';
+ $href = htmlspecialchars($match[1], ENT_QUOTES, 'UTF-8');
+ $link_text = htmlspecialchars($match[1], ENT_QUOTES, 'UTF-8');
+ return '<' . array_push($links, "<a $attr href=\"mailto:{$href}\">{$link_text}</a>") . '>';
}, $value) ?: $value;
break;
default:
$value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) {
- return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\">$protocol://{$match[1]}</a>") . '>';
+ $href = htmlspecialchars("$protocol://{$match[1]}", ENT_QUOTES, 'UTF-8');
+ $link_text = htmlspecialchars("$protocol://{$match[1]}", ENT_QUOTES, 'UTF-8');
+ return '<' . array_push($links, "<a $attr href=\"{$href}\">{$link_text}</a>") . '>';
}, $value) ?: $value;
break;
}
Source: GitHub Commit 265379b. The patch applies htmlspecialchars($value, ENT_QUOTES, 'UTF-8') to both the href attribute and the visible link text across the URL, mail, and default protocol branches of linkify().
Detection Methods for CVE-2026-40565
Indicators of Compromise
- Inbound emails containing URLs with embedded " characters followed by HTML attribute names such as onerror=, onmouseover=, or onclick=.
- Stored conversation bodies in the FreeScout database containing anchor tags with unexpected attributes injected after the href value.
- Outbound requests from agent browsers to attacker-controlled domains immediately after a ticket is opened.
Detection Strategies
- Inspect FreeScout database tables holding conversation threads for anchor tags whose href value contains a literal " followed by an event handler keyword.
- Apply web server access log analysis to identify GET requests originating from agent sessions to unfamiliar external hosts shortly after ticket views.
- Run static review of installed FreeScout versions against the 1.8.213 release tag to confirm the linkify() patch is present.
Monitoring Recommendations
- Forward FreeScout application logs and web server access logs to a centralized analytics platform for correlation of email ingestion and agent ticket views.
- Alert on Content Security Policy (CSP) violation reports from the FreeScout web interface, which often indicate XSS execution attempts.
- Monitor agent account behavior for anomalous API calls or session activity following exposure to suspect inbound messages.
How to Mitigate CVE-2026-40565
Immediate Actions Required
- Upgrade FreeScout to version 1.8.213 or later, which contains the htmlspecialchars() fix in app/Misc/Helper.php.
- Audit recent inbound email content for crafted URLs containing " characters and remove or quarantine affected conversations.
- Force re-authentication for FreeScout agent accounts if exposure to malicious tickets is suspected.
Patch Information
The vendor fix is available in the FreeScout 1.8.213 Release. The code change is documented in the GitHub Security Advisory GHSA-49pm-xwqj-vwjp and the corresponding GitHub Commit 265379b. Administrators should apply the upstream release rather than backporting the diff manually to ensure all related sanitization paths are updated.
Workarounds
- Deploy a strict Content Security Policy on the FreeScout web interface to block inline event handlers and unauthorized script sources.
- Configure inbound mail filtering to reject or sanitize messages containing URLs with embedded quote characters until the patch is applied.
- Restrict FreeScout administrative interfaces to trusted networks via reverse proxy or VPN until upgrade can be scheduled.
# Configuration example: upgrade FreeScout to the patched release
cd /var/www/freescout
sudo -u www-data git fetch --tags
sudo -u www-data git checkout 1.8.213
sudo -u www-data php artisan freescout:after-app-update
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

