{"id":"GHSA-h5fh-7hwr-97mw","aliases":["CVE-2026-44298"],"title":"Kimai has an arbitrary file read in its invoice PDF renderer (admin)","titleSource":"OSV","descriptionSource":"OSV","declaredSeverity":"MODERATE","description":"## Summary\n\nUsers 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. \n\nThis 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.\n\n## Root cause\n\n1. `src/Twig/SecurityPolicy/StrictPolicy.php:123-128` explicitly whitelists `PdfContext::setOption()`:\n   ```php\n   if ($obj instanceof PdfContext) {\n       if ($lcm !== 'setoption') { throw ...; }\n       return;\n   }\n   ```\n\n2. `src/Pdf/MPdfConverter.php` keeps `associated_files` in the pass-through allowlist:\n   ```php\n   $allowed = ['mode','format','default_font_size','default_font', ... , 'associated_files','additional_xmp_rdf'];\n   ```\n   and then forwards it to mPDF:\n   ```php\n   if (array_key_exists('associated_files', $options) && is_array($options['associated_files'])) {\n       $associatedFiles = $options['associated_files'];\n       unset($options['associated_files']);\n   }\n   ...\n   $mpdf->SetAssociatedFiles($associatedFiles);\n   ```\n\n3. mPDF 8.3.1 `MetadataWriter::writeAssociatedFiles()` calls `file_get_contents`, which respects PHP stream wrappers:\n   ```php\n   if (isset($file['path'])) {\n       $fileContent = @file_get_contents($file['path']);\n   }\n   ...\n   $filestream = gzcompress($fileContent);\n   $this->writer->write('<</Type /EmbeddedFile');\n   ```\n\nThe sandbox and the option allowlist were both written defensively (short whitelists, not blacklists), but neither side considered that `associated_files` is a PDF/A file-embedding feature whose `path` key is a sink.\n\n## Fix\n\nThe implemented fix has two aspects:\n\n1. The `PdfContext` now works with a strict allow-list, that excludes `associated_files`\n2. The `MPdfConverter` now removes any `path` from the `$associatedFiles` array, which can still be used by plugins:\n```php\n        if (\\count($associatedFiles) > 0) {\n            // remove \"path\" so mPDF will not use file_get_contents() on local files\n            // callers must pre-read and pass the bytes via \"content\"\n            $associatedFiles = array_map(static function ($entry): array {\n                if (!\\is_array($entry)) {\n                    return [];\n                }\n\n                if (\\array_key_exists('path', $entry)) {\n                    unset($entry['path']);\n                }\n\n                return $entry;\n            }, $associatedFiles);\n            $mpdf->SetAssociatedFiles($associatedFiles);\n        }\n\n```","severity":"medium","score":4.1,"published":"2026-05-08T22:22:36.000Z","modified":"2026-05-08T22:41:25.472Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Packagist","name":"kimai/kimai","sources":[{"name":"OSV · GHSA-h5fh-7hwr-97mw","url":"https://osv.dev/vulnerability/GHSA-h5fh-7hwr-97mw"}],"ranges":[{"events":[{"introduced":"2.32.0"},{"fixed":"2.56"}],"type":"ECOSYSTEM"}],"versions":["2.32.0","2.33.0","2.34.0","2.35.0","2.35.1","2.36.0","2.36.1","2.37.0","2.38.0","2.39.0","2.40.0","2.41.0","2.42.0","2.43.0","2.44.0","2.45.0","2.46.0","2.47.0","2.48.0","2.49.0","2.50.0","2.51.0","2.52.0","2.53.0","2.54.0","2.55.0"],"fixed":["2.56"]}],"sourceAffected":[],"references":["https://github.com/kimai/kimai/security/advisories/GHSA-h5fh-7hwr-97mw","https://nvd.nist.gov/vuln/detail/CVE-2026-44298","https://github.com/kimai/kimai","https://github.com/kimai/kimai/releases/tag/2.56.0"],"sources":[{"name":"OSV","id":"GHSA-h5fh-7hwr-97mw","modified":"2026-05-08T22:41:25.472680Z","url":"https://osv.dev/vulnerability/GHSA-h5fh-7hwr-97mw"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:N/A:N","score":4.1}],"products":[],"remediation":[],"kev":{"status":"not-listed","checkedAt":"2026-10-28T22:00:32.546Z"},"coverage":[{"source":"NVD","status":"not-checked"},{"source":"GHSA","status":"not-checked"},{"source":"EUVD","status":"not-checked"},{"source":"EPSS","status":"not-checked"}],"evidence":[]}