Kimai has an arbitrary file read in its invoice PDF renderer (admin)
Date: 2026-05
Affected: composer/kimai/kimai
Attack vector: path-traversal
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-44298
CWE: CWE-22
CVSS: 4.1 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:N/A:N)

## Summary Users with the role `System-Admin` (`ROLE_SYSTE_ADMIN`) and the permission `upload_invoice_template` can upload PDF invoice templates, which can call `pdfContext.setOption('associated_files', ...)` inside the sandboxed Twig render. This is forwarded to mPDF's `SetAssociatedFiles()`, whose writer calls `file_get_contents($entry['path'])` during PDF output and embeds the bytes as a FlateDecode stream in the PDF. Any file readable by the PHP worker is returned to the attacker inside the rendered invoice. ## Root cause 1. `src/Twig/SecurityPolicy/StrictPolicy.php:123-128` explicitly whitelists `PdfContext::setOption()`: ```php if ($obj instanceof PdfContext) { if ($lcm !== 'setoption') { throw ...; } return; } ``` 2. `src/Pdf/MPdfConverter.php` keeps `associated_files` in the pass-through allowlist: ```php $allowed = ['mode','format','default_font_size','default_font', ... , 'associated_files','additional_xmp_rdf']; ``` and then forwards it to mPDF: ```php if (array_key_exists('associated_files', $options) && is_array($options['associated_files'])) { $associatedFiles = $options['associated_files']; unset($options['associated_files']); } ... $mpdf->SetAssociatedFiles($associatedFiles); ``` 3. mPDF 8.3.1 `MetadataWriter::writeAssociatedFiles()` calls `file_get_contents`, which respects PHP stream wrappers: ```php if (isset($file['path'])) { $fileContent = @file_get_contents($file['p


Mitigations:

Architectural layers (MAESTRO):