{"id":"CVE-2026-42267","aliases":["GHSA-3xc2-h5r3-wv3r"],"url":"https://o3.security/vulnerability/CVE-2026-42267","summary":"Kimai: Formula Injection via tag names in XLSX export","details":"## Summary\n\nAny `ROLE_USER` can create a tag with a formula string as its name (e.g. `=SUM(54+51)`) via `POST /api/tags` and assign it to a timesheet. When an admin exports timesheets to XLSX, `ArrayFormatter.formatValue()` joins tag names with `implode()` and returns the result unchanged. OpenSpout promotes any `=`-prefixed string to a `FormulaCell`, writing `<f>SUM(54+51)</f>` into the XLSX archive. Excel evaluates the formula when the file is opened.\n\n## Details\n\n### 1. `ArrayFormatter` does not sanitize before returning\n\n`sanitizeDDE()` exists on `StringHelper` and is called by `TextFormatter`, but `ArrayFormatter` never calls it.\n```php\n// src/Export/Package/CellFormatter/ArrayFormatter.php:24\nreturn implode(', ', $value);  // no sanitizeDDE() call\n```\n\n### 2. Tag name validation does not block formula trigger characters\n\nThe API blocks commas in tag names but permits `=`, `+`, `-`, and `@` - all valid formula prefixes in Excel and LibreOffice Calc.\n\n### 3. OpenSpout silently promotes strings to formula cells\n\n`Cell::fromValue(\"=SUM(54+51)\")` returns a `FormulaCell` with no warning.\n\n### PoC\n\n1. It logs in as normal user, creates tag `=SUM(54+51)`, assigns it to a timesheet.\n2. Admin has to export timesheets to Excel version via `/en/export/` endpoint.\n\n<img width=\"1339\" height=\"700\" alt=\"image\" src=\"https://github.com/user-attachments/assets/884c7943-5e3b-4647-8bcc-e264d6719d66\" />\n\n<img width=\"1304\" height=\"128\" alt=\"formula_injection_tags\" src=\"https://github.com/user-attachments/assets/ef28f2ad-7491-4a15-bb18-1fcd6ff5e55a\" />\n\n## Impact\n\n- Any `ROLE_USER` can plant a formula that executes on the workstation of any user who exports and opens timesheet data\n- A single malicious tag poisons all future exports across all users and date ranges until the tag is deleted\n\n## Fixes\n\n1. Prevent `=` being part of the tag name (and other fields as well)\n2. Use OpenSpout `TextCell` for everything that is a string","published":"2026-05-08T03:28:52.226Z","modified":"2026-10-28T02:31:10.956239987Z","cvss":null,"epss":{"score":0.0022,"percentile":0.12475,"asOf":"2026-09-11"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"kimai/kimai","fixedVersion":"2.54.0"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/kimai/kimai/releases/tag/2.54.0"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/42xxx/CVE-2026-42267.json"},{"type":"ADVISORY","url":"https://github.com/kimai/kimai/security/advisories/GHSA-3xc2-h5r3-wv3r"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-42267"},{"type":"PACKAGE","url":"https://github.com/kimai/kimai"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:31:10.956239987Z"}}