GitHub Advisoryadvisory · Packagist
GHSA-qh43-xrjm-4ggp Kimai's User Preferences API allows standard users to modify restricted attributes: hourly_rate, internal_rate
MEDIUM
Official page ↗
- Aliases
- CVE-2026-40486
- Ecosystem
- Packagist
- Packages
- kimai/kimai
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
- Weaknesses
- CWE-915
- Reviewed
- 2026-04-15
Affected packages
• Packagist kimai/kimai: < 2.53.0 → fixed in 2.53.0
Description
Summary
A Mass Assignment / Broken Object Property Level Authorization (BOPA) vulnerability in the User Preferences API allows any authenticated user (even those with the lowest privileges) to arbitrarily modify restricted financial attributes on their profile, specifically their `hourly_rate` and `internal_rate`.
Details
Kimai restrictively protects the `hourly_rate` and `internal_rate` parameters during standard GUI flow. Users lacking the `hourly-rate` role permissions cannot see or edit these fields via the standard Web Form (`UserApiEditForm` / `UserEditType`).
The vulnerability exists in the dedicated preferences API endpoint: `src/API/UserController.php::updateUserPreference`.
When a `PATCH` request is sent to `/api/users/{id}/preferences`, the endpoint iterates through the submitted JSON array and blindly applies the new values:
```php
foreach ($request->request->all() as $preference) {
// ... validation omitted ...
if (null === ($meta = $profile->getPreference($name))) {
throw $this->createNotFoundException(\sprintf('Unknown custom-field "%s" requested', $name));
}
$meta->setValue($value); // setEnabled(false)`).
However, the `updateUserPreference` API endpoint entirely ignores this `isEnabled()` flag and forcefully saves the mutated object to the database natively via Doctrine ORM. This allows unauthorized accounts to manipulate the business-logic variables calculating their own financial earnings.
PoC
1. Log into Kimai as an unprivileged, standard employee account (a user with absolutely no `roles` array privileges).
2. Capture the `cookie` or Session cookies. (In this example, the user's ID is `2`).
3. Send the following cURL request (or intercept via Burp Suite) targeting your own user ID:
```bash
curl -i -X PATCH "http://localhost:8001/api/users/2/preferences" \
-H "Content-Type: application/json" \
-H "cookie: " \
-d '[
{
"name": "hourly_rate",
"value": "1337"
},
{
"name": "internal_rate",
"value": "1337"
}
]'
```
4. The server responds with `HTTP/1.1 200 OK`. (Note: The `hourly_rate` will intentionally NOT appear in the JSON echo due to `User::getVisiblePreferences` sanitizing output based on the same disabled flag).
5. If an Administrator organically views User 2's profile within Kimai, or if the user logs any new timesheets, the active and billed `hourly_rate` applied to their account will be confirmed as `1337`.
Impact
This is a Privilege Escalation and Business Logic Flaw impacting the core financial calculations of the application. An attacker with a standard user account can manipulate their own billing rate multipliers unbeknownst to administrators, resulting in fraudulent invoices, distorted timesheet exports, and unauthorized financial tampering.
Related
Alias · CVE (1)
- CVE-2026-40486 Kimai is an open-source time tracking application. vulnerability
Weakness · CWE (1)
- CWE-915 Improperly Controlled Modification of Dynamically-Determined Object Attributes weakness