GHSA-vrqv-52x7-rm4v: Kimai/kimai Kimai's Twig Function Config() Leaks Vulnerability
MODERATEGHSA-vrqv-52x7-rm4v is a MODERATE kimai's twig function config() leaks vulnerability (CWE-693: Protection Mechanism Failure) affecting Kimai/kimai libraries in the Packagist ecosystem. The issue involves kimai's twig function config() leaks server-wide secrets (ldap bind password, saml sp private key) via invoice/export templates. Remediation is available by upgrading affected packages to version 2.56.0.
GHSA-vrqv-52x7-rm4v at a Glance
How to Fix GHSA-vrqv-52x7-rm4v
To remediate this vulnerability, upgrade all affected Kimai/kimai dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade kimai/kimai to 2.56.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for kimai/kimai
How to Check if You Are Affected
To determine whether your application is affected by GHSA-vrqv-52x7-rm4v, inspect your project dependencies for Kimai/kimai:
inspect dependencies for kimai/kimai
Analyze the terminal output to locate any version of Kimai/kimai in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.56.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-693: Protection Mechanism Failure, where the product does not use or incorrectly uses a protection mechanism that provides sufficient defense against directed attacks against the product. In Kimai/kimai, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-vrqv-52x7-rm4v Affected Kimai/kimai Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
kimai/kimai
|
Packagist |
< 2.56.0
|
2.56.0
|
References
Frequently Asked Questions
What is GHSA-vrqv-52x7-rm4v?
Which Kimai/kimai versions are affected?
What version fixes GHSA-vrqv-52x7-rm4v?
Is kimai/kimai affected?
What CWE is associated with GHSA-vrqv-52x7-rm4v?
How can I check Packagist dependencies for GHSA-vrqv-52x7-rm4v?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-vrqv-52x7-rm4v",
"modified" : "2026-05-06T18:42:30Z",
"published" : "2026-05-06T18:42:30Z",
"aliases" : [ ],
"summary" : "Kimai's Twig function config() leaks server-wide secrets (LDAP bind password, SAML SP private key) via invoice/export templates",
"details" : "### Summary\n\nKimai's Twig sandbox (`StrictPolicy`, used for admin-uploaded invoice and export templates) allow-lists the `config()` Twig function with no key filtering. `config(name)` delegates to `App\\Configuration\\SystemConfiguration::find($name)`, which returns arbitrary entries from the flattened `kimai.config` container parameter built in `App\\DependencyInjection\\AppExtension::loadInternal()`. Any admin who can upload a Twig template can therefore render server-wide secrets - the LDAP bind password, the SAML SP private key, and any other dotted configuration key populated from `kimai.yaml` - into the invoice or export output, which is then delivered to whoever generates an invoice or export from that template (including lower-privileged users such as teamleads with invoice permissions). This is a second, uncovered class of the same defense-in-depth issue patched in GHSA-rh42-6rj2-xwmc: the previous fix added a User-method blocklist but left the `config()` function unrestricted.\n\n### Details\n\n`src/Twig/SecurityPolicy/StrictPolicy.php:40-55` explicitly allow-lists `'config'`:\n\n```php\nprivate array $allowedFunctions = [\n 'max', 'min', 'range', 'constant', 'cycle', 'random', 'date',\n 't',\n 'encore_entry_css_source', 'encore_entry_link_tags', 'encore_entry_script_tags',\n 'is_granted',\n 'qr_code_data_uri',\n 'config', // <-- sink, no key filter\n 'create_date', 'month_names', 'locale_format',\n 'class_name'\n];\n```\n\n`src/Twig/Configuration.php:22-45` is the Twig function implementation:\n\n```php\npublic function getFunctions(): array\n{\n return [new TwigFunction('config', [$this, 'get'])];\n}\n\npublic function get(string $name)\n{\n switch ($name) {\n case 'chart-class': return '';\n case 'theme.chart.background_color': return '#3c8dbc';\n // ... 4 more theme constants\n }\n return $this->configuration->find($name); // <-- arbitrary key lookup\n}\n```\n\n`App\\Configuration\\SystemConfiguration::find()` at `src/Configuration/SystemConfiguration.php:54-62` is a direct dictionary lookup. The dictionary `$this->settings` is initialised from the `kimai.config` container parameter, which the `AppExtension` flattens from `kimai.yaml` into dotted-notation keys.\n```\n\nThe LDAP and SAML schemas declared in `src/DependencyInjection/Configuration.php` define secret-valued scalar nodes that survive the flattening and become reachable keys:\n\n```php\n// getLdapNode()\n->arrayNode('connection')\n ->children()\n ->scalarNode('host')->defaultNull()->end()\n ->scalarNode('username')->end()\n ->scalarNode('password')->end() // -> settings['ldap.connection.password']\n ...\n\n// getSamlNode()\n->arrayNode('sp')\n ->children()\n ->scalarNode('x509cert')->end()\n ->scalarNode('privateKey')->end() // -> settings['saml.connection.sp.privateKey']\n ...\n```\n\nThe invoice and export renderers both enable the sandbox against `StrictPolicy` and pass the shared Twig environment - the one with the `config` function registered - into sandboxed rendering: `src/Invoice/Renderer/AbstractTwigRenderer.php:66-74` and `src/Export/Base/{PDFRenderer,HtmlRenderer}.php`. An admin who uploads a malicious invoice or export template therefore gets an unrestricted read primitive against `kimai.config`.\n\nIn a real deployment the attacker template is uploaded through the admin UI (ROLE_SUPER_ADMIN, permission `upload_invoice_template`), saved by `src/Invoice/InvoiceTemplate*` and later rendered by whoever generates an invoice or export for that template. The rendering user is typically a teamlead or admin with invoice permission (`INVOICE` permission set: `['view_invoice','create_invoice','manage_invoice_template']`, granted to ROLE_ADMIN and ROLE_TEAMLEAD in `config/packages/kimai.yaml`). The rendered output is returned as the invoice PDF/HTML or as a CSV/XLSX export, so the secrets land in a document that is routinely downloaded and emailed.\n\n### Impact\n\nAny Kimai deployment that (a) has SAML or LDAP configured in `kimai.yaml`, and (b) has at least one user (other than the current SUPER_ADMIN) who will render a template-based invoice or export in the future, is affected. A malicious or compromised SUPER_ADMIN can upload a template once, leave, and subsequent invoice or export generations by teamleads or other admins silently exfiltrate `ldap.connection.password`, `saml.connection.sp.privateKey`, `saml.connection.sp.x509cert`, and any other dotted configuration key into an attacker-readable artifact. The LDAP bind password gives domain-credential access to the company directory and often to every downstream system that trusts the same directory; the SAML SP private key allows an attacker to forge signed SAML assertions to any service provider that trusts the same key pair. This is the same class of defense-in-depth leak that GHSA-rh42-6rj2-xwmc patched for user-level secrets, at a broader impact because the keys leaked here are system-wide rather than per-user, and the current StrictPolicy does not intercept the `config()` call path. \n\n### Solution\n\nThe `config()` function was patched to only return a pre-configured list of settings in sandboxed mode. \n\nAdditional checks were added to prevent access to configs that start with `saml.` or `ldap.`.\n\nKimai will not issue a CVE, because this requires a SUPER_ADMIN account and it only affects system with activated LDAP or SAML, which also uses the invoice system.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Packagist",
"name" : "kimai/kimai"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "2.56.0"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 2.55.0"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/kimai/kimai/security/advisories/GHSA-vrqv-52x7-rm4v"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/kimai/kimai"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-693" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-06T18:42:30Z",
"nvd_published_at" : null
}
}