Blog

TeamCity Vulnerability: CVE-2023-42793 and CVE-2024-27198

TeamCity vulnerability guide: CVE-2023-42793, CVE-2024-27198, CVE-2024-27199 and CVE-2026-63077, and how to keep the build server off the internet.

9 min read
Karolis Rusenas
On this page

TeamCity On-Premises has had four unauthenticated or near-unauthenticated vulnerabilities that attackers exploited in the wild, and every one of them needs only network reach to the server. The most reliable fix besides patching is to stop exposing the server. Most TeamCity servers are public for one reason, receiving VCS webhooks, which an outbound relay can deliver without any inbound port.

This guide covers CVE-2023-42793, CVE-2024-27198, CVE-2024-27199 and CVE-2026-63077, then shows how to keep the server private and still trigger builds.

The TeamCity vulnerability timeline

Our Threat Watch records for these four are below. "Auth needed" means authentication before the attacker acts; none of these needs an account.

CVEWhat an attacker getsAuth neededExploited in the wildFixed in
CVE-2023-42793, authentication bypass to RCE (CVSS 9.8)Skip authentication, run code on the server, take administrative controlNoneYes. Microsoft attributed attacks to North Korean groups (Diamond Sleet, Onyx Sleet); CISA and partners attributed large-scale exploitation to Russia's SVR; CISA flags ransomware use2023.05.4
CVE-2024-27198, authentication bypass to admin (CVSS 9.8)Administrator actions such as creating admin users or tokens, server takeoverNoneYes. Mass exploitation reported from 2024-03-06; JetBrains reported ransomware encryption at two customers; CISA flags ransomware use2023.11.4
CVE-2024-27199, path traversal (CVSS 7.3)A limited set of protected pages and servlets: information disclosure and some changes such as replacing the HTTPS certificateNoneCISA KEV listing (added 2026-04-20) with a ransomware flag; no separate public report naming actors2023.11.4
CVE-2026-63077, unauthenticated RCE via the agent polling protocol (CVSS 9.8)Run operating system commands as the server process, exposing configuration, stored credentials and build pipelinesNoneYes. CISA KEV on 2026-08-05; JetBrains reported active exploitation on 2026-08-072025.11.7 and 2026.1.3

Affected versions: all On-Premises versions before 2023.05.4 for the first, through 2023.11.3 for the next two, and all versions before the listed fixes for the last. TeamCity Cloud was not affected by CVE-2023-42793 and needs no action for CVE-2026-63077. Vendor advisories: JetBrains on CVE-2023-42793, on CVE-2024-27198 and CVE-2024-27199, and on CVE-2026-63077.

Why build servers get ransomed

A build server holds the things an attacker wants: source code, deployment credentials, signing certificates and a mechanism that runs code on other machines. Administrative control of TeamCity is therefore close to administrative control of everything it builds and deploys.

The table shows the pattern. The flaws sit in authentication handling, in the server's request routing and in the agent protocol. They are reachable by anything that can open a TCP connection to the server. For CVE-2024-27198, GuidePoint suspected BianLian ransomware but could not say whether it or CVE-2023-42793 was the entry point. The common factor is not one bug, it is that the server was reachable.

Why exposure is the risk multiplier

Patching is mandatory, but the window between a fix and your upgrade is where mass exploitation happens. For CVE-2024-27198 the fix and technical details were published on 2024-03-04 and mass exploitation was reported two days later. A server that is not reachable from the internet cannot be hit during that window by an anonymous scanner.

So the question is why the server is public. For most teams the honest answer is that GitHub or GitLab must send a push event. That is a narrow requirement served by an entire public web application: login page, REST API, every plugin's endpoints and any pre-auth bug in the version you run. The same dynamic is covered for Jenkins in Securing Jenkins.

Expose the webhook, not the server

Reachable from the internetShould stay private
One public HTTPS input URL on the relay, accepting the VCS provider's deliveriesThe TeamCity web UI and login
The whole /app/rest/ API
Plugin endpoints and the agent polling endpoint
The server's own HTTPS port

With Webhook Relay, the agent connects out from your network. The provider posts to the relay's public URL, and the relay streams the event down the agent's connection to an address only the agent can reach. TeamCity needs no public IP and no inbound firewall rule.

What TeamCity expects: the commit-hook endpoint

JetBrains documents the recommended commit-hook shape in Configuring VCS post-commit hooks for TeamCity. A hook sends a POST to:

<TeamCityServerURL>/app/rest/vcs-root-instances/commitHookNotification?locator=<vcsRootInstancesLocator>

Per that page:

  • The request does not start builds. It makes TeamCity check the matching VCS roots for new changes, and your VCS triggers then start the builds.
  • The locator should identify specific VCS root instances. JetBrains recommends matching on the repository URL through a nested property:(name:url,value:...,matchType:equals,ignoreCase:true) locator, with colons and slashes in the URL escaped.
  • The request must authenticate. JetBrains lists a username with a personal access token, and its generic script sends Authorization: Bearer <access-token>. The user needs the "View project and all parent projects" and "View build configuration settings" permissions on the projects that use the VCS root.

GitHub's push webhook does not carry a TeamCity locator or a TeamCity access token, so a function between the relay and TeamCity builds that request.

Step by step with Webhook Relay

This works for TeamCity when the relay agent runs on a host that can reach the server, for example http://teamcity.internal:8111. Replace the hostname, bucket name and function name with yours.

1. Create a dedicated TeamCity user and token. Give it only the two view permissions listed above, create a personal access token for it, and store that token as a secret connection in Webhook Relay. Do not use an administrator's token.

2. Install the agent next to TeamCity and log in using the CLI installation steps:

curl https://my.webhookrelay.com/webhookrelay/downloads/install-cli.sh | bash
relay login -k YOUR_TOKEN_KEY -s YOUR_TOKEN_SECRET

On a container host you can run the Docker agent instead, with RELAY_KEY, RELAY_SECRET and BUCKETS set.

3. Create a function that turns a GitHub delivery into the TeamCity call, using the request methods from the modify request page. Verify the GitHub HMAC signature first, as shown in the filter webhooks page, then rewrite the request:

const token = require("secret:teamcity-token")

// 1. Verify GitHub's X-Hub-Signature-256 over the raw body here (see the
//    signature guide), and call r.stopForwarding() on mismatch.

// 2. Only pushes should prompt a check for changes
const eventType = r.headers["X-Github-Event"] || r.headers["x-github-event"]
if (eventType !== "push") {
  r.stopForwarding()
  return
}

// 3. Rewrite the request into TeamCity's commit-hook call
r.setMethod("POST")
r.setPath("/app/rest/vcs-root-instances/commitHookNotification")
r.setRawQuery("locator=<your escaped VCS root instance locator>")
r.setHeader("Authorization", "Bearer " + token)

Header, method, path and query setting are documented functions on the modify-request page; the locator value is yours to fill in following JetBrains' syntax. Read the final URL in the bucket logs to confirm the path is exactly the endpoint above. Keep the r.setPath line: the output points at TeamCity's base address, so the function setting the path on every delivery (and stopping everything that is not a push) is what prevents a sender from appending /app/rest/... or any other TeamCity path to the input URL. Never attach this output without the function.

4. Forward to TeamCity's base address with the function attached to the output:

relay forward --bucket teamcity-hooks --function teamcity-commit-hook http://teamcity.internal:8111

The command creates the bucket if needed and prints its public input URL. --function attaches a function to the output (flag reference). Use relay service install and relay service start, or the Docker agent, to keep it running.

5. Point GitHub at the printed URL with the push event, and set the same secret you verify in step 3. A successful call returns text like "Scheduled checking for changes for 1 VCS roots", per JetBrains' troubleshooting section. See the broader webhooks in CI/CD guide for the pattern.

6. Close the public port. Remove the public DNS name, port forward or load-balancer rule for TeamCity, and reach the UI over a VPN.

The simpler alternative: let TeamCity poll

JetBrains states that TeamCity periodically polls remote repositories targeted by each active VCS root to detect changes, and positions hooks as a way to cut polling load and speed up detection. If you can accept polling latency and your VCS root count is modest, you need no webhook and no inbound access. The relay path earns its place when you have many roots or need prompt builds.

Hardening that still matters

  • Patch. Upgrade to 2023.05.4, 2023.11.4, 2025.11.7 or 2026.1.3 or later. Patch plugins fix only the CVEs JetBrains lists for them.
  • Assume compromise if it was exposed and unpatched. Check for unexpected admin users and tokens, new plugins or build steps and scheduled tasks. Rotate every credential and signing key reachable from TeamCity. For CVE-2026-63077, JetBrains suggests searching logs for com.thoughtworks.xstream.converters.ConversionException and reviewing unauthorized agents, especially names starting with scan.
  • Authentication. Use a least-privilege token for the hook. See webhook security best practices.
  • Signature verification. The relay changes where traffic enters, not whether to trust it. Verify GitHub's signature in the function, before forwarding, so unsigned requests get a 401 at the relay and never reach TeamCity; see how to verify a webhook signature.
  • Filtering. Drop events that should not cause a check, such as everything except pushes.
  • Least privilege. Run the server with minimum OS privileges, on a host separate from agents.

Honest limits: when the relay does not help

  • Agents connect from outside. CVE-2026-63077 is in the agent polling protocol. The relay only helps if your build agents sit on the same private network as the server or reach it over a VPN. If agents must connect from the internet, patch and restrict access instead.
  • The webhook path itself is vulnerable. Anything the relay forwards still reaches TeamCity. Verifying the signature at the relay limits that to requests GitHub actually signed, so an anonymous attacker cannot reach the handler. A flaw triggered by content inside a genuine delivery would still get through.
  • People need the UI from outside. Use a VPN or identity-aware proxy; a webhook relay does not publish your UI.
  • It does not replace patching. An internal attacker or a compromised agent can still use these flaws against an unpatched server.

More self-hosted tools that are public only for webhooks

For hosted deliveries to a private CI server in general, see receiving webhooks on localhost. To close the port today, create a free account.

Frequently asked questions

What is the TeamCity vulnerability CVE-2023-42793?

CVE-2023-42793 is an authentication bypass in TeamCity On-Premises (CVSS 9.8) that lets anyone who can reach the server over HTTP(S) skip authentication, run code on it and take administrative control. All versions before 2023.05.4 are affected; TeamCity Cloud is not. It is exploited in the wild and CISA lists it as used in ransomware campaigns.

What is CVE-2024-27198 in TeamCity?

CVE-2024-27198 is an unauthenticated authentication bypass that lets a remote attacker with no account perform administrator actions such as creating admin users or tokens. All TeamCity On-Premises versions through 2023.11.3 are affected and 2023.11.4 fixes it. Mass exploitation was reported from 2024-03-06 and ransomware activity followed.

Which TeamCity versions fix these vulnerabilities?

2023.05.4 fixes CVE-2023-42793. 2023.11.4 fixes CVE-2024-27198 and CVE-2024-27199. 2025.11.7 and 2026.1.3 fix CVE-2026-63077. Run a version at or above the newest fix for your release line, or install JetBrains' security patch plugin as a stopgap; each plugin fixes only the CVEs JetBrains names for it.

Should a TeamCity server be exposed to the internet?

No. Four critical or high TeamCity On-Premises flaws since 2023 let unauthenticated attackers reach administrative functions or run code, and all four are on CISA's Known Exploited Vulnerabilities list. Keep the server on a private network or behind a VPN, and let a relay deliver only the webhook deliveries it needs.

How do I get GitHub webhooks to TeamCity without exposing it?

Give GitHub a Webhook Relay bucket URL, run the relay agent on the same network as TeamCity, and attach a function to the output that rewrites each delivery into POST /app/rest/vcs-root-instances/commitHookNotification?locator=... with an Authorization header carrying a TeamCity access token. TeamCity then checks the VCS root for changes. It needs no inbound port.

Do I need a webhook at all for TeamCity?

No. TeamCity polls the VCS roots of each active build configuration on its own, so it detects new commits without any inbound access. Webhooks only make detection faster and reduce polling load on servers with many VCS roots. If a few minutes of delay is acceptable, polling alone is the simplest secure setup.

Does an outbound relay protect against CVE-2026-63077?

Only if your build agents run on the same private network as the server. CVE-2026-63077 is in the agent polling protocol, and agents outside the network still need to reach the server. If agents connect from the internet, patch to 2025.11.7 or 2026.1.3 and restrict access as far as you can.