Introduction
A one-line code change in OPNsense's user synchronization script was all that separated authenticated administrators from root-level command execution on the underlying FreeBSD system. CVE-2026-44194, patched in OPNsense 26.1.8 on May 12, 2026, shows how a benign design choice, allowing email addresses as usernames, can combine with an unsafe shell invocation to create a critical OS command injection path.
OPNsense is an open source FreeBSD-based firewall and routing platform maintained by Deciso BV, a Netherlands-based company. It is widely deployed across small to medium businesses, data centers, and government environments as an alternative to commercial firewall products. Because it sits at the network perimeter, a bug like this carries extra weight: compromising the firewall gives an attacker a foothold at the network boundary.
Technical Information
The vulnerability is in the local user synchronization flow in core/src/opnsense/scripts/auth/sync_user.php. When a user is added or modified through the OPNsense web UI or API, this script runs a shell command via mwexecf to signal the backend through pluginctl. The vulnerable code concatenates the $username variable directly into the command string using PHP's . (concatenation) operator:
mwexecf('/usr/local/sbin/pluginctl -c user_changed ' . $username);
OPNsense validates usernames at the UI and API levels, but it explicitly permits valid email addresses as account names. That is where the injection becomes possible.
RFC 5321 Quoted Local Parts as an Injection Vector
RFC 5321 defines the structure of email addresses, and the local part (the portion before the @ symbol) may contain a quoted string. Inside those quotes, characters that are normally shell metacharacters, such as backticks, semicolons, and pipes, are legal email characters. An attacker can construct a username like:
"`id>/conf/proof.txt`"@example.com
This value passes the application's email validation because it is a structurally valid email address. But when the username is concatenated into the shell command string and executed, the shell interprets the backtick-enclosed content as a subshell command. Because mwexecf ultimately runs with root privileges, the injected command executes as uid=0(root).
Attack Flow
Exploitation runs through these steps:
- The attacker authenticates to OPNsense with an account that holds user management privileges. This permission is commonly delegated to helpdesk staff or junior administrators, which widens the realistic attacker pool.
- The attacker sends a POST request to the
/api/auth/user/add/endpoint with a JSON body containing a crafted username whose quoted local part embeds shell commands. - OPNsense's input validation accepts the username because it conforms to email address syntax rules.
- The
sync_user.phpscript receives the username and concatenates it directly into thepluginctlshell command. - The shell interprets the metacharacters within the username, executing the embedded commands as root.
- The attacker gets arbitrary command execution with full root privileges on the firewall.
The classification is CWE-78 (Improper Neutralization of Special Elements used in an OS Command), which is exactly what happens here: user-controlled data flows into a shell command without neutralization of special characters.
Proof of Concept
A public Proof of Concept is available directly within the GitHub Security Advisory GHSA-f59w-m967-9rf6, published on May 12, 2026 by the OPNsense project. The vulnerability was reported by Konstantinos Spartalis (@sopex).
An authenticated user with user management privileges can use the OPNsense API to create a new user with a malicious username. The advisory gives two examples.
Example 1: Execute id and write proof to disk
curl -k -u <api key> \ -H 'Content-Type: application/json' \ -X POST http://<IP>/api/auth/user/add/ \ -d '{"user": {"name": "\"`id>/conf/proof.txt`\"@example.com", "password": "TestPass123", "scrambled_password": "0"}}'
This writes uid=0(root) gid=0(wheel) groups=0(wheel) to /conf/proof.txt, confirming root-level execution.
Example 2: Shut down the firewall
curl -k -u <api key> \ -H 'Content-Type: application/json' \ -X POST http://<IP>/api/auth/user/add/ \ -d '{"user": {"name": "\"`/sbin/shutdown${IFS}-p${IFS}now`\"@example.com", "password": "TestPass123", "scrambled_password": "0"}}'
Note the use of ${IFS} (Internal Field Separator) to stand in for spaces within the quoted local part, a common shell injection technique when spaces are restricted or awkward in the injection context.
Patch Information
OPNsense fixed CVE-2026-44194 with a one-line change in src/opnsense/scripts/auth/sync_user.php. The patch was authored by Konstantinos Spartalis (GitHub user sopex, who also reported the vulnerability) and committed by OPNsense lead maintainer Franco Fichtner on May 12, 2026. It was first merged to master as commit f35e2bf and then cherry-picked to the stable/26.1 branch as commit 9f201fe, shipping as part of OPNsense 26.1.8.
The fix replaces the unsafe string concatenation with parameterized argument passing through mwexecf()'s own format string mechanism:
@@ -84,7 +84,7 @@ * In theory there could be other handlers registered to the same event, which is the reason * we will signal it here */ - mwexecf('/usr/local/sbin/pluginctl -c user_changed ' . $username); + mwexecf('/usr/local/sbin/pluginctl -c user_changed %s', [$username]); echo json_encode(["status" => "updated"]); } else { echo json_encode(["status" => "not_found"]);
This is the parameterized command pattern applied to shell execution. When arguments are passed via the %s placeholder and provided as an array, mwexecf() internally applies escapeshellarg() to each argument before interpolating it into the command string. Any shell metacharacters (backticks, $() subshell syntax, semicolons, pipes) are escaped and treated as literal data rather than executable code. The username still reaches pluginctl as intended, but the shell can no longer interpret any embedded commands.
The OPNsense 26.1.8 release announcement on the official forum corroborates this fix, noting: "properly escape username in sync_user.php command invoke."
Affected Systems and Versions
All OPNsense core versions prior to 26.1.8 are affected. Specifically:
- Vulnerable: OPNsense versions up to and including 26.1.7
- Fixed: OPNsense 26.1.8
The vulnerability requires an authenticated session with user management privileges. Any OPNsense deployment where the web UI or API is reachable by users holding this permission level is at risk.
Vendor Security History
Organizations managing OPNsense deployments should note that several critical vulnerabilities landed in a short window. Across versions 26.1.7 and 26.1.8, OPNsense patched three significant vulnerabilities:
| Vulnerability | Affected Component | Required Privilege | Fixed Version |
|---|---|---|---|
| CVE-2026-44193 | XMLRPC configuration restore | XMLRPC Library | 26.1.7 |
| CVE-2026-44194 | User management synchronization | User management | 26.1.8 |
| CVE-2026-45158 | DHCPv4 settings | Page interfaces | 26.1.8 |
Each vulnerability required a different privilege level, and together they make for a concentrated run of critical security updates. Deciso BV turned patches around quickly and documented each one through public advisories.
References
- NVD Entry for CVE-2026-44194
- GitHub Security Advisory GHSA-f59w-m967-9rf6: RCE on user management
- OPNsense 26.1.8 Release Announcement (Official Forum)
- Patch Commit f35e2bf on GitHub
- Commit History for sync_user.php on stable/26.1
- OPNsense 26.1.8: Two Critical RCE Bugs (wz-it.com)
- OPNsense Addresses Code Execution Issue with PoC Available (Field Effect)
- CVE-2026-44193 Advisory (GHSA-xxp9-93cr-x54p)
- About OPNsense / Deciso BV



