Cross-Site Request Forgery (CSRF) in kevinpapst/kimai2
Description
Kimai2 is vulnerable to Cross-Site Request Forgery (CSRF), allowing attackers to perform unauthorized actions on behalf of authenticated users.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Kimai2 is vulnerable to Cross-Site Request Forgery (CSRF), allowing attackers to perform unauthorized actions on behalf of authenticated users.
Vulnerability
Kimai2 is vulnerable to Cross-Site Request Forgery (CSRF) attacks. This vulnerability affects versions prior to the commit that introduced proper CSRF token handling for invoice creation and search operations [1][3]. The application did not validate or refresh CSRF tokens on certain endpoints, leaving them open to forged requests.
Exploitation
An attacker can exploit this by crafting a malicious link or webpage that, when visited by an authenticated Kimai2 user, triggers unauthorized requests to the application. The attacker does not need to be authenticated, but the victim must have an active session. The attack can be performed by tricking the user into clicking a link or visiting a compromised site that automatically submits a form or sends a request to the vulnerable endpoints [3][4].
Impact
Successful exploitation allows an attacker to perform actions on behalf of the victim, such as creating invoices or modifying search parameters, leading to unauthorized changes and potential data integrity issues. The attacker can trick the user into performing actions without their consent [1].
Mitigation
The vulnerability is fixed in commit 1da26e04 [3]. Users should update to the latest version of Kimai2, which includes the CSRF token fixes. If immediate update is not possible, ensure that users are cautious of clicking on untrusted links or visiting suspicious sites while logged into the application [4].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
kevinpapst/kimai2Packagist | < 1.16.7 | 1.16.7 |
Affected products
2- kevinpapst/kevinpapst/kimai2v5Range: unspecified
Patches
11da26e041df6fix invoice create and search (#2990)
3 files changed · +17 −4
src/Controller/AbstractController.php+2 −0 modified@@ -218,6 +218,8 @@ protected function handleSearch(FormInterface $form, Request $request): bool } } + $request->query->remove('_token'); + if ($request->query->has('resetSearchFilter')) { $data->resetFilter(); $this->removeLastSearch($data);
src/Controller/InvoiceController.php+10 −3 modified@@ -66,7 +66,7 @@ public function __construct(ServiceInvoice $service, InvoiceTemplateRepository $ * @Route(path="/", name="invoice", methods={"GET", "POST"}) * @Security("is_granted('view_invoice')") */ - public function indexAction(Request $request, SystemConfiguration $configuration): Response + public function indexAction(Request $request, SystemConfiguration $configuration, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->templateRepository->hasTemplate()) { if ($this->isGranted('manage_invoice_template')) { @@ -100,6 +100,8 @@ public function indexAction(Request $request, SystemConfiguration $configuration return $this->redirectToRoute('invoice'); } + $csrfTokenManager->refreshToken('invoice.create'); + try { return $this->renderInvoice($query, $request); } catch (Exception $ex) { @@ -148,6 +150,7 @@ public function previewAction(Customer $customer, Request $request, SystemConfig if ($form->isValid()) { try { + $query->setCustomers([$customer]); $model = $this->service->createModel($query); return $this->service->renderInvoiceWithModel($model, $this->dispatcher); @@ -167,7 +170,7 @@ public function previewAction(Customer $customer, Request $request, SystemConfig * @Security("is_granted('access', customer)") * @Security("is_granted('create_invoice')") */ - public function createInvoiceAction(Customer $customer, InvoiceTemplate $template, Request $request, SystemConfiguration $configuration): Response + public function createInvoiceAction(Customer $customer, InvoiceTemplate $template, Request $request, SystemConfiguration $configuration, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->templateRepository->hasTemplate()) { return $this->redirectToRoute('invoice'); @@ -185,9 +188,13 @@ public function createInvoiceAction(Customer $customer, InvoiceTemplate $templat return $this->redirectToRoute('invoice'); } + $csrfTokenManager->refreshToken('invoice.create'); + $query = $this->getDefaultQuery(); $form = $this->getToolbarForm($query, $configuration->find('invoice.simple_form')); - $form->submit($request->query->all(), false); + if ($this->handleSearch($form, $request)) { + return $this->redirectToRoute('invoice'); + } if ($form->isValid()) { $query->setTemplate($template);
src/Form/Extension/SelectWithApiDataExtension.php+5 −1 modified@@ -75,8 +75,12 @@ public function buildView(FormView $view, FormInterface $form, array $options) } while (($parent = $parent->getParent()) !== null); $formPrefix = implode('_', array_reverse($formPrefixes)); + $formField = $apiData['select']; - $formField = $formPrefix . '_' . $apiData['select']; + // forms with prefix (like toolbar & search) would result in a wrong field name "_foo" instead of "foo" + if ($formPrefix !== '') { + $formField = $formPrefix . '_' . $apiData['select']; + } $view->vars['attr'] = array_merge($view->vars['attr'], [ 'data-form-prefix' => $formPrefix,
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-4jwx-78vx-gm6gghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-4033ghsaADVISORY
- github.com/kevinpapst/kimai2/commit/1da26e041df62c10bd8075d78f2db7854d3eee07ghsax_refsource_MISCWEB
- huntr.dev/bounties/e05be1f7-d00c-4cfd-9390-ccd9d1c737b7ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.