tine: The Export Template Is Compiled by Twig Without a Sandbox

The export takes any template the caller names and compiles it in a Twig environment with no sandbox.

Advisory ID: TP-2026-098
Product: tine (groupware and CRM, PHP)
Vulnerability type: Server-side template injection (CWE-1336)
CVE: requested (GitHub CNA), assignment pending
CVSS 3.1: 9.9 (Critical) · CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Affected versions: <= 2025.11.12
Vendor advisory: GHSA-cqm5-7q48-7wc7
Fixed in: 2024.11.23, 2025.11.13 and weekly-2026.35.1
Reported: 21 August 2026

Summary

tine's document export compiles a template with Twig. Which template that is, the caller decides, because the export methods pass the request's options through, and within them the template field overrides the template with any file from the Filemanager. The Twig environment that compiles that file's body registers no sandbox, so a placeholder in the document is evaluated as an unrestricted Twig expression. Through a known pattern in Twig 2, that expression reaches system() in PHP. No export-specific permission check exists, and the shipped Users group carries both Addressbook and Filemanager, so no elevated account is needed.

Root cause

Tinebase_Export_Abstract sets the export template from the caller-supplied node id in options.template (tine20/Tinebase/Export/Abstract.php:331), guarded only by an allowlist of the file extensions doc, docx, xls, xlsx, ods and odt (:340). Tinebase_Export_Doc::renderProcessorsTwigTemplate compiles that template's body with $this->_twig->load($twigName)->render(...) (tine20/Tinebase/Export/Doc.php:396). The matching Twig environment is built with no SandboxExtension and no SecurityPolicy, neither of which appears anywhere under Tinebase/Export/ or Tinebase/Twig*. The bundled twig/twig is version 2.16.1pl1, in which the string-callable pattern reaches system() in PHP. The _export method runs no export-specific right check, and the default Users group holds Addressbook and Filemanager.

Proof of Concept

# 1. as an ordinary user, upload a file with a permitted extension
#    into the Filemanager whose body carries the placeholder:
${twig:['id']|filter('system')}

# 2. start an export naming that template:
Addressbook.exportContacts  with  options.template = <node id of the file>

# the template is compiled with no sandbox, the expression reaches
# system() and runs the command as the application user.

No special setting is required; the path is reachable in a stock install, and accounts are created by the administration, with no self-registration.

Impact

  • Execution of arbitrary shell commands as the application user by any ordinary account.
  • Access to the configuration including the database credentials, and with them the data of every tenant on the installation.
  • Persistent access to the server, since the attacker can place their own files and start services.
  • No elevated right needed, as the shipped Users group already carries Addressbook and Filemanager.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.