CVE

CVE-2025-54531

Path Traversal while extracting plugins in JetBrains TeamCity before 2025.07 allowed Arbitrary File Write on Windows.

  • Application/component: JetBrains TeamCity
  • Affected version: < 2025.07
  • Score (CVSS 3.1): 7.7 High
  • Vector: CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:L
  • CWEs:CWE-23: Relative Path Traversal

During a more detailed analysis of JetBrains TeamCity, I identified a vulnerability.

Description

JetBrains TeamCity allows additional plugins to be installed from ZIP files. While the upload mechanism on Linux and macOS correctly protects against conventional Zip Slip attacks, a critical vulnerability exists on Windows: specially crafted file paths containing backslashes (..\) allow an Arbitrary File Write outside the plugin directory, including the ability to overwrite existing files.

The result is Remote Code Execution on the TeamCity host, without the plugin having to be enabled. Uploading it is sufficient.

This article explains the vulnerability, the technical background, and the Proof-of-Concept attack path.

Technical background

TeamCity recursively extracts uploaded plugin ZIP files on the server. To prevent Directory Traversal, TeamCity filters typical Unix path sequences such as:

../
/../

These filters work reliably on Linux and macOS. On Windows, however, paths are interpreted using backslashes (\). This is where the problem lies:

..\..\..\webapps\ROOT\404.jsp

The current filtering logic does not detect this path, but the Windows file system API correctly interprets it as traversal during extraction.

An attacker can therefore write or overwrite files anywhere outside the plugin directory, provided that the TeamCity process has write permission.

Impact

  • Arbitrary File Write on the host system
  • Existing files can be overwritten
  • No file extension restrictions (.jsp, .exe, .bat, .lnk, …)
  • The plugin does not need to be enabled
  • If TeamCity runs as SYSTEM on Windows, full system compromise is possible (JetBrains explicitly recommends against this!)

A particularly straightforward attack path is to overwrite a JSP file in the TeamCity web root and place a webshell.

Proof of Concept – attack chain

1. Creating the malicious ZIP file

The ZIP file must be created on Linux. Python on Windows normalizes backslashes to forward slashes, which prevents the exploit from working there.

Example entry in the ZIP:

..\..\..\webapps\ROOT\404.jsp

During extraction, the file is placed directly in the TeamCity web directory. In 7-Zip, it looks like this: 7Zip example

2. Uploading the plugin

The ZIP file is uploaded normally through “Upload plugin zip” in the TeamCity interface. TC Upload

Important: The plugin does not need to be enabled. Extraction occurs as part of the upload.

3. Restarting TeamCity

After the server restarts, the manipulated file is loaded. TC Restart

In my PoC, the default 404.jsp was overwritten.

4. Triggering the webshell

Requesting a nonexistent page executes the new 404.jsp—in my case, a simple JSP webshell. This achieves Remote Code Execution on the host. TC Webshell

Exploit stealth

An attacker can discreetly integrate the payload into a legitimate plugin, such as a well-known community plugin. Because the ZIP file is extracted recursively, a single manipulated path entry anywhere in the archive is sufficient.

An administrator would not expect a plugin upload to modify the system directly, which makes this attack technique particularly deceptive.

Root Cause

The filtering logic validates only Unix path separators (/). Windows path separators (\) are not normalized or checked correctly.

Mitigation

  • Normalize backslashes to forward slashes before validating paths
  • Restrict extracted paths to the destination directory
  • Use secure ZIP extractors with canonical path checks

Because the vulnerability affects Windows exclusively, Linux and macOS are unaffected.

Note

All tests were performed on my own local instance and with test user data that I created myself.

JetBrains responded quickly, constructively, and professionally.


Timeline

  • Reported to JetBrains on June 13, 2025
  • Response received on June 13, 2025
  • Issue fixed on July 7, 2025
  • Patch released on July 20, 2025
  • CVE entry published as CVE-2025-54531 on July 28, 2025
  • Blog post with details released on January 25, 2026