CVE-2026-52825
Executive Summary
CVE-2026-52825 is an improper authorization vulnerability (CWE-285) in Kimai, an open-source time-tracking application. Prior to version 2.58.0, the REST endpoints POST /api/teams/{id}/members/{userId} and POST /api/teams/{id}/activities/{activityId} verify only that the caller is a team lead with edit rights on the target team, but fail to verify that the referenced User or Activity is within the team lead's own accessible scope. This allows a low-privileged team lead to bind out-of-scope users and activities to a team they control, potentially poisoning downstream authorization decisions that trust team membership (e.g., RolePermissionManager::checkTeamAccessActivity()).
Kimai is typically deployed as a web-facing time-tracking and reporting platform for SMBs, agencies, and enterprise cost-accounting teams. A successful exploit lets an authenticated team lead escalate visibility and control over data they should not be able to reach, corrupting time entries, project assignments, reporting, and workflow logic across the tenant. There is currently no public PoC, no exploit code, no Nuclei template, and the CVE is not in CISA KEV; EPSS is 0.00270 (~19.2nd percentile), indicating low but non-zero predicted exploitation activity.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability is a classic server-side authorization bypass of the "confused deputy" / broken object-level authorization family, mapped to CWE-285: Improper Authorization. The attack surface is the authenticated REST API of Kimai, specifically two team-management endpoints:
POST /api/teams/{id}/members/{userId}POST /api/teams/{id}/activities/{activityId}
At the time of the bug, both endpoints applied a coarse authorization gate: they confirmed that the caller may edit the Team identified by {id} (i.e., the caller holds a team-lead role or equivalent edit capability). What they did not do was enforce the second, object-level check on the referenced resource:
- For the members endpoint, no check was performed against
access_userfor the referenced{userId}— the team lead's own manageable user scope was never consulted. - For the activities endpoint, no check was performed for
viewaccess on the referenced{activityId}.
The intended enforcement for both the UI and the form-driven code paths lives in TeamEditForm and UserRepository::getQueryBuilderForFormType(), which deliberately restrict the candidate users/activities a team lead can pick to those inside the team lead's manageable scope. In other words, the UI presented a narrowed, safely-filtered list. The API endpoints bypassed that narrowing entirely by accepting arbitrary identifiers from the caller and persisting the resulting membership/activity relationship.
The bug is therefore not a filter bypass on input parsing and not an injection flaw; it is a missing object-level access-control check on the referenced resource. It is a textbook Broken Object Level Authorization (BOLA) pattern analogous to OWASP API Security Top 10 API1:2023.
The reason this is more than a cosmetic defect lies in the downstream trust model. Once a foreign user or activity is successfully attached to a team that the attacker is able to edit, other components — most notably RolePermissionManager::checkTeamAccessActivity() — treat that membership as authoritative. The NVD text explicitly states that the resulting relationships "can be trusted by RolePermissionManager::checkTeamAccessActivity() and other team-based authorization, visibility, reporting, and workflow logic." This is the heart of the impact: the attacker writes a persistent authorization primitive into the data model, and the application's own authorization engine then honors it. The result is privilege amplification via data integrity, not via memory corruption, RCE, or credential theft.
Because the exploit requires an authenticated session and an existing team-lead role, the pre-conditions are:
- Valid low-privilege credentials with team-lead (team edit) capability on at least one team.
- Knowledge or guessing of
{userId}/{activityId}values that lie outside the caller's own scope. Kimai's identifiers are typically sequential integers, which makes enumeration trivial once any valid identifier is observed. In multi-tenant or departmental deployments this may require knowledge of another team's users or activities, but in many Kimai installs such values are leaked via reports, exports, or shared project listings.
No public exploit and no Nuclei template exist, so the precise minimal request body and any additional header requirements cannot be authoritatively stated from the provided data. The CVSS vector above is a conservative estimate for this authorization-bypass class (network reachable, requires low privileges, no user interaction, high confidentiality and integrity impact on tenant-scoped data, no availability impact); the authoritative score for CVE-2026-52825 was not published by NVD in the supplied dataset.
Exploitation Scenarios
No public PoC is available; the attack chain below is inferred strictly from the vulnerability class (BOLA / missing object-level authorization) and the endpoints and identifiers named in the NVD description. No implementation specifics beyond those explicitly stated have been invented.
1) Reconnaissance / target identification.
The attacker first identifies an internet-facing or internally reachable Kimai instance (Shodan dorks: http.title:"Kimai", http.html:"kimai", application favicon hash). With a valid low-privilege account — either legitimate, self-registered, or obtained via credential stuffing against Kimai's login — the attacker authenticates and enumerates the team API to identify a team whose {id} they are permitted to edit. They also enumerate {userId} and {activityId} values visible in their normal scope, then pivot to guessing/collecting identifiers outside that scope (Kimai uses numeric object IDs, which are enumerable).
2) Triggering the specific flaw class.
The attacker sends an authenticated request to POST /api/teams/{id}/members/{userId} or POST /api/teams/{id}/activities/{activityId}. The endpoint confirms the caller can edit team {id} (which is true), but does not consult access_user for {userId} or view access for {activityId}. Because the object-level check is missing, the request succeeds even when {userId}/{activityId} refer to resources outside the team lead's manageable scope — that is the entire width of the vulnerability.
3) Payload / execution method (vulnerability-class level).
At the vulnerability-class level, the "payload" is simply an out-of-scope object identifier placed in the URL path. There is no memory-corruption payload, no script injection, no file upload. The exploit primitive is the act of writing an unauthorized membership row (user→team) or activity association (activity→team) into the Kimai data store via the REST API. The success criterion is an HTTP 2xx response for a request that the equivalent UI (TeamEditForm) would have refused to construct, because UserRepository::getQueryBuilderForFormType() would not have offered that user in the dropdown.
4) Post-exploitation impact.
Once the foreign user/activity is bound into the attacker-editable team, downstream logic that trusts team membership — most importantly RolePermissionManager::checkTeamAccessActivity() and other team-based authorization, visibility, reporting, and workflow routines — will honor the new relationship. The attacker thereby gains, through the application's own trusted code paths, visibility and control over time entries, projects, and activity data belonging to users/activities that were never delegated to them. The relationships are persistent and survive session termination, so the effect is a durable authorization-primitive injection rather than a one-shot request tampering. Combined with reporting and workflow trust, this can also enable integrity attacks against downstream cost reports, billing exports, and approval workflows that consume Kimai team data.
No evidence of exploit-in-the-wild, no KEV listing, and no known threat-actor campaign at the time of writing.
Impact Assessment
- Confidentiality (High, C:H in the estimated vector): A team lead can attach users and activities they should not see to a team they control, and downstream logic that trusts team membership may then surface that data to them via reports, views, and exports.
- Integrity (High, I:H): The attacker can create unauthorized, persistent membership and activity relationships in the authorization data model. Because downstream components trust team membership, this is effectively a write primitive against the application's own authorization state.
- Availability (None/Unset in estimate): No explicit denial-of-service effect is described.
- Attack vector: Network (AV:N), Privileges required: Low (PR:L), User interaction: None (UI:N), Scope: Unchanged (S:U).
Blast radius. Any Kimai deployment below 2.58.0 that (a) exposes the REST API to authenticated users, and (b) issues team-lead roles to more than one trust level of user. In practice this is the common multi-team SMB/agency Kimai deployment: department leads who should only manage their own staff and activities can cross-wire data into teams they control. In a single-tenant, single-admin Kimai install the impact is negligible because there is no privilege gradient to cross. In multi-department or multi-tenant Kimai installs (including MSSP-hosted Kimai with logical tenant separation via teams), the impact is a tenant-boundary weakening: one team lead can import another team's users and activities into their own team, and downstream authorization that keys off team membership will follow.
Business impact. Time-tracking data feeds invoicing, payroll, utilization reporting, and compliance/audit trails. Corrupting or cross-linking these records can distort billing, breach confidentiality obligations, and undermine audit evidence. Detection is difficult in isolation because the malicious requests are legitimate, well-formed, authenticated API calls against documented endpoints; the only tell is that the referenced object lies outside the caller's scope.
Detection Guidance
Because exploitation is a correctly-formed authenticated request against an in-scope endpoint with an out-of-scope object ID, network-level detection is weak in isolation and depends on correlating the caller's normal team scope with the object IDs they submit. The rules below target the two named API endpoints and (where possible) require that the referenced identifier be inconsistent with the caller's known scope. Implementations should tune user/team/activity ID ranges to their environment.
Sigma Rule
title: Kimai Team Lead Adds Out-of-Scope Member or Activity via API (CVE-2026-52825)
id: 5b9c3e0a-7a11-4f4c-9c1e-kimai52825001
status: experimental
description: Detects POST requests to Kimai team member/activity API endpoints, indicative of exploitation of CVE-2026-52825 prior to 2.58.0.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-52825
author: valtersit.com
date: 2026/01/01
logsource:
category: webserver
product: apache
detection:
selection_method:
cs-method: 'POST'
selection_uri:
cs-uri-stem|re: '^/api/teams/[0-9]+/(members|activities)/[0-9]+$'
condition: selection_method and selection_uri
fields:
- c-ip
- cs-username
- cs-uri-stem
- sc-status
falsepositives:
- Legitimate team-lead management of in-scope users/activities
level: medium
tags:
- attack.t1190
- cve.2026.52825
Note: web-server access logs do not carry the caller's team-scope; treat hits as candidates and correlate with Kimai application logs/audit trail showing the actor, team id, and target object id.
YARA Rule
rule CVE_2026_52825_Kimai_Team_Scope_Bypass_Logs
{
meta:
author = "valtersit.com"
description = "Detects HTTP request paths targeting vulnerable Kimai team member/activity endpoints (CVE-2026-52825) in application, proxy, or access logs"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-52825"
date = "2026-01-01"
severity = "medium"
strings:
$ep_members = "/api/teams/" ascii nocase
$ep_end_mem = "/members/" ascii nocase
$ep_end_act = "/activities/" ascii nocase
$post = "POST " ascii nocase
condition:
uint16(0) == 0x0A or filesize < 100MB
and $ep_members
and ( $ep_end_mem or $ep_end_act )
and $post
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-52825 Kimai Team Lead Adds Out-of-Scope Member via API"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/api/teams/"; pcre:"/\/api\/teams\/[0-9]+\/members\/[0-9]+$/Ri"; classtype:attempted-user; reference:cve,2026-52825; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-52825; sid:5282501; rev:1;)
alert http any any -> any any (msg:"CVE-2026-52825 Kimai Team Lead Adds Out-of-Scope Activity via API"; flow:established,to_server; http.method; content:"POST"; http.uri; content:"/api/teams/"; pcre:"/\/api\/teams\/[0-9]+\/activities\/[0-9]+$/Ri"; classtype:attempted-user; reference:cve,2026-52825; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-52825; sid:5282502; rev:1;)
Elastic Detection
sequence by user.name, source.ip with maxspan=5m
[ http where http.request.method == "GET" and
http.request.uri : "/api/teams/*" ]
[ http where http.request.method == "POST" and
http.request.uri regex ".*/api/teams/[0-9]+/(members|activities)/[0-9]+" and
http.response.status_code >= 200 and http.response.status_code < 300 ]
Enrichment recommended: join
http.request.uriobject IDs againstuser.name's known team-membership scope; alert only when the referenced user/activity ID lies outside that scope. In many SOCs the raw sequence above is still a strong high-signal candidate list because legitimate team edits usually originate from the UI, not the raw API path.
Splunk SPL Query
index=web OR index=proxy sourcetype=access_combined OR sourcetype=apache_access
method=POST
uri_path=*/*
| rex field=uri_path "(?<api_path>\/api\/teams\/(?<team_id>\d+)\/(?<object_type>members|activities)\/(?<object_id>\d+))"
| where isnotnull(api_path) AND status>=200 AND status<300
| stats count min(_time) as first_seen max(_time) as last_seen
values(team_id) as team_ids values(object_type) as object_types
values(object_id) as object_ids
by src_ip, user
| sort - count
Add a
lookup team_scope_by_actor(CSV) keyed onusermapping actor → allowed team_ids, then filter whereobject_idis not present in the actor's scope lookup. Raw hits are still worth reviewing because legitimate UI-driven edits rarely use the raw REST path.
Wazuh OSSEC Rule
<group name="kimai,web,accesslog,">
<rule id="528251" level="8">
<decoded_as>web-accesslog</decoded_as>
<match>POST /api/teams/</match>
<regex>\/api\/teams\/\d+\/(members|activities)\/\d+</regex>
<description>CVE-2026-52825: Kimai team-scope bypass attempt - team lead adding out-of-scope member/activity via API (POST).</description>
<mitre>
<id>T1190</id>
</mitre>
<group>cve_2026_52825,authorization_bypass,</group>
</rule>
<rule id="528252" level="10">
<if_sid>528251</if_sid>
<status>^(200|201|204)$</status>
<description>CVE-2026-52825: Kimai team-scope bypass SUCCEEDED (2xx response) - out-of-scope user/activity added to team; investigate immediately.</description>
<group>cve_2026_52825,authorization_bypass,post_exploitation,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 2/4 — CLAIMED. The only claimed fix is in NVD/OSV stating "This issue is fixed in version 2.58.0." This has not been independently confirmed by a second authoritative source, so security teams should verify with the Kimai maintainers' release notes and commit history before relying on it in a formal SLAs.
1) Immediate mitigations (if upgrade cannot be applied now):
- Restrict access to the REST API. Place
/api/behind mutual TLS, a VPN, or an SSO-aware reverse proxy that only exposes the API to trusted networks/clients. CVE-2026-52825 requires authenticated API access; blocking broad API exposure materially reduces the attack surface even if the code is unpatched. - Enforce least privilege on team-lead roles. Audit every account holding team-edit rights and remove the privilege from anyone who does not need it.
- Strict input validation at the edge. Use a WAF/proxy rule that flags or blocks
POST /api/teams/*/members/*andPOST /api/teams/*/activities/*originating from agent identifiers not normally associated with automated provisioning, or that submit object IDs outside an allow-list of the caller's known team scope (if your identity/proxy layer can express that). - Increase logging. Enable Kimai audit logging and retain web access logs for the two named endpoints so any exploitation attempt is captured for forensic review.
- Monitor for the detection rules above; false-positive rate for the raw-path rules is low because legitimate team edits normally flow from the UI (
TeamEditForm) rather than the raw REST verb.
2) Patch / upgrade steps:
- Confirm the installed Kimai version (the project's version endpoint or
composer show kimai/kimaion the server). - If version < 2.58.0, plan an upgrade to Kimai 2.58.0 or later. Follow the official Kimai upgrade procedure (back up the database and
var/directory, run the documented migration steps, then redeploy). - After upgrade, re-verify the two endpoints behave correctly: an authenticated team lead with edit rights on a team should receive a failure response when referencing a user/activity outside their own scope — this is the definitive confirmation the missing
access_user/viewchecks have been restored. - Verify the fix against the maintainer's release notes and, ideally, the corresponding upstream commit, since patch confidence here is CLAIMED (single source).
3) Long-term hardening:
- Adopt object-level authorization tests as part of CI: for every mutating REST endpoint that takes an object ID (
members/{userId},activities/{activityId}, and any future equivalents), assert that the caller's scope is consulted, mirroring the guard rails already present inTeamEditFormandUserRepository::getQueryBuilderForFormType(). - Standardize a shared authorization helper so UI-form filtering and API endpoint checks cannot diverge — the root cause here is that the UI filtered the candidate list while the API did not re-validate the submitted ID.
- Rotate and inventory low-privilege credentials and API tokens; remove dormant team-lead accounts.
- Monitor CISA KEV and vendor advisories for future Kimai authorization issues; this class (BOLA/CWE-285) is the most likely recurring pattern in team-based permissions systems.
- Where multi-tenant isolation depends on teams, document that teams are an authorization primitive and require the same review rigor as roles.
References
- NVD — CVE-2026-52825: https://nvd.nist.gov/vuln/detail/CVE-2026-52825
- OSV — package advisory entry for CVE-2026-52825: https://osv.dev/vulnerability/CVE-2026-52825
- Kimai project (upstream maintainers) — release notes / changelog for version 2.58.0 (verify fix commit): https://github.com/kimai/kimai/releases
- CWE-285 — Improper Authorization: https://cwe.mitre.org/data/definitions/285.html
- OWASP API Security Top 10 (2023) — API1: Broken Object Level Authorization (attack-class reference for this vulnerability family): https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
Exploit-in-the-wild / threat-actor status: No known exploit code, no public PoC, no Nuclei template, and not listed in CISA KEV. EPSS 0.00270 (~19.2nd percentile). Predicted exploitation activity is low but non-zero; treat as a low-priority patch for exposed multi-tenant Kimai deployments and a routine patch for single-tenant installs.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.