high · 8.7CVE-2026-54347Aug 18, 2026

CVE-2026-54347: Froxlor Stored XSS in DNS TXT Record Leads to Admin Account Takeover

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A customer-level Froxlor user can store JavaScript in a DNS TXT record that executes in any administrator's browser, handing the attacker full control of the panel.

Packagefroxlor/froxlor
Ecosystemcomposer
Affected<= 2.3.7
Fixed in2.3.8
CVE-2026-54347: Froxlor Stored XSS in DNS TXT Record Leads to Admin Account Takeover

The problem

Froxlor's DNS editor accepts TXT record content, strips only non-printable bytes, and stores the result verbatim. HTML special characters such as < and > pass through unmodified.

When an administrator opens the DNS editor for the affected domain, the stored value is passed through a Text::wordwrap() callback and rendered into the page via a Twig |raw filter with no escaping. The script executes immediately on page load, no click required.

The panel's Content-Security-Policy also includes 'unsafe-inline', so CSP provides no protection.

Proof of concept

A working proof-of-concept for CVE-2026-54347 in froxlor/froxlor, with the exact payload below.

html
<img src=x onerror=alert(document.domain)>

Three code locations chain to produce the vulnerability. DomainZones.php only runs preg_replace('/[^\x09\x20-\x7E]/', '', $content), which accepts < (0x3C) and > (0x3E) without encoding them. The Text::wordwrap() display callback then calls PHP's wordwrap() on the raw value and returns it as a plain string.

The Twig table template hits the {{ td.data|raw }} branch for any non-iterable callback result, so the browser receives the angle brackets intact and executes the injected tag.

The fix in 2.3.8 (commit a1d8f425b11ef7597949018814afa056a842cba0) applies htmlspecialchars() before wordwrap() in the callback, so < and > become &lt; and &gt; before they ever reach the template. CWE-79.

The fix

Upgrade to froxlor/froxlor 2.3.8 or later. The patch escapes special characters in the Text::wordwrap() display callback before the value reaches the Twig |raw branch. As an additional hardening step, remove 'unsafe-inline' and 'unsafe-eval' from the Content-Security-Policy header in lib/Froxlor/UI/Panel/UI.php.

Reporter not attributed.

References: [1][2][3][4]

Related research