CVE-2026-100713: Froxlor before 2.3.12 Privilege Escalation via SSH Key Sync
Froxlor 2.3.10 and earlier contain a time-of-check time-of-use (TOCTOU) race condition in the SSH key synchronization cron (lib/Froxlor/Cron/System/SshKeys.php, SshKeys::generateFiles). The containment/symlink validation performed by FileDir::makeCorrectDir()/makeCorrectFile() is done only at check time; the live filesystem path is re-resolved as root at write time (fileputcontents with FILEAPPEND|LOCKEX, followed by chmod/chown/chgrp), with a database round-trip and file reads in between, and no path or file-descriptor pinning (no ONOFOLLOW or openat2(RESOLVENOSYMLINKS)). On installations where the non-default setting system.allowcustomershell=1 grants customers local shell access, a customer can atomically swap their ~/.ssh directory for a symlink after the check and before the write, causing the root-run cron to append the customer's public key to /root/.ssh/authorizedkeys and to chown /root/.ssh to the customer, resulting in full root compromise of the panel host. The cron re-runs on every interval, allowing unlimited attempts. This is a residual race that bypasses the check-time fix introduced for GHSA-mq5v-... . The issue is fixed in Froxlor 2.3.12.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
Froxlorto a version that resolves this vulnerability.Fixed in 2.3.12
Event History
Frequently Asked Questions
Which deployments are realistically exposed?
The described attack requires system.allow_customer_shell=1, a non-default setting that gives customers local shell access. Installations without customer shell access are not described as exploitable through this path.
What access does an attacker need?
An attacker needs a customer account with local shell access and the ability to manipulate their ~/.ssh directory during SSH key synchronization. Exploitation also depends on winning a TOCTOU race while the root-run cron job processes the path.
How can the issue lead to host compromise?
A successful race can redirect the root-run cron's write to /root/.ssh/authorized_keys, adding the customer's public key. The subsequent ownership changes can also make /root/.ssh customer-owned, resulting in full root compromise of the panel host.
What can be done if upgrading is not immediately possible?
Disable system.allow_customer_shell to remove the customer local-shell prerequisite described for this attack. The cron runs repeatedly, so leaving that setting enabled permits unlimited race attempts.
Which versions are affected and which version fixes it?
Froxlor 2.3.10 and earlier are identified as affected. The issue is fixed in Froxlor 2.3.12.