Introduction
A one line code change in OPNsense's user synchronization script was all that separated authenticated administrators from full root level command execution on the underlying FreeBSD system. CVE-2026-44194, patched in OPNsense 26.1.8 on May 12, 2026, demonstrates how a seemingly benign design choice (allowing email addresses as usernames) can interact with unsafe shell invocation patterns 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. Its position as a perimeter security device makes vulnerabilities of this nature particularly consequential, since compromising the firewall gives an attacker a foothold at the network boundary.
Technical Information
The vulnerability exists in the local user synchronization flow within core/src/opnsense/scripts/auth/sync_user.php. When a user is added or modified through the OPNsense web UI or API, this script invokes 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);
While OPNsense validates usernames at the UI and API levels, it explicitly permits compliant email addresses to be used as account names. This 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 these quotes, characters that are normally shell metacharacters, such as backticks, semicolons, and pipes, are considered syntactically legal email characters. An attacker can construct a username like:
"`id>/conf/proof.txt`"@example.com
This value passes the application's email validation checks because it is a structurally valid email address. However, when the username is concatenated into the shell command string and executed, the shell interprets the backtick enclosed content as a subshell command. Because the mwexecf function ultimately runs with root privileges, the injected command executes as uid=0(root).
Attack Flow
The exploitation proceeds 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 broadens 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 achieves 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 precisely what occurs 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. Two examples are provided in the advisory:
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 substitute for spaces within the quoted local part, a common shell injection technique when spaces are restricted or problematic in the injection context.
Patch Information
OPNsense addressed CVE-2026-44194 with a precise, surgical one line fix 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 a textbook example of 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. This means 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 accessible to users holding this permission level is at risk.
Vendor Security History
The discovery of multiple critical vulnerabilities within a short timeframe is worth noting for organizations managing OPNsense deployments. 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 different privilege levels, representing a concentrated window of critical security updates. Deciso BV demonstrated a rapid response cycle, releasing patches and maintaining transparency 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



