TeamCity — Unauthenticated RCE via Agent Polling Deserialization (CVE-2026-63077)
Published: 2026-08-09 • Researcher: Rapid7 Labs (Stephen Fewer)
Exploitation signals
Confirmed exploited in the wild. Added to CISA KEV 2026-08-05. Federal remediation deadline 2026-08-08.
EPSS 1.0% · 60th percentile
- Severity
- Critical
- CVE
- CVE-2026-63077
- Category
- web
- Affected product
- JetBrains TeamCity (on-premises CI/CD server), agent polling subsystem
- Affected versions
- TeamCity 2023.11 through 2026.03
- Disclosed
- 2026-08-09
- Patch status
- Patched
Tags
References
Archive entry
intelseclab/poc-archiveOn this page
Metadata
| Field | Value |
|---|---|
| Date Added | 2026-08-09 |
| Last Updated | 2026-08-09 |
| Author / Researcher | Rapid7 Labs (Stephen Fewer) |
| CVE / Advisory | CVE-2026-63077 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (CVSSv3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| Status | Patched |
| Tags | jetbrains, teamcity, preauth-rce, xstream, deserialization, hsqldb, polyglot, jsp, CWE-502, agent-polling, ci-cd |
| Related | — |
Affected Target
| Field | Value |
|---|---|
| Software / System | JetBrains TeamCity (on-premises CI/CD server), agent polling subsystem |
| Versions Affected | TeamCity 2023.11 through 2026.03 |
| Language / Platform | Java, HSQLDB, XStream; exploit in Python 3 |
| Authentication Required | No — the agent registration and error-command endpoints are unauthenticated |
| Network Access Required | Remote — the exploit reaches TeamCity over HTTP/HTTPS |
Summary
CVE-2026-63077 is an unauthenticated remote code execution vulnerability in JetBrains TeamCity. The agent polling subsystem accepts XML payloads from unregistered agents and deserializes them with XStream without any authentication or sanitization. An attacker can craft an XStream gadget chain that writes a polyglot SQL/JSP file to the TeamCity webroot through HSQLDB SCRIPT, then triggers the dropped JSP to execute an arbitrary operating system command as the TeamCity service account.
The vulnerability is reachable over HTTP with no credentials, no agent token, and no prior registration — the POST /app/agents/v1/register and POST /app/agents/v1/commands/error endpoints are exposed by default. Rapid7 discovered and disclosed the issue; the public PoC is their own research tool released alongside their technical analysis.
Vulnerability Details
Root Cause
TeamCity uses XStream to deserialize XML payloads sent by build agents. The agent polling flow allows an unauthenticated caller to register a synthetic agent session and then deliver an arbitrary XStream serialization graph through the error-reporting endpoint. XStream, when configured without a denylist, resolves any Java class the attacker names — including gadget-chain primitives that chain into Runtime.exec().
The exploit uses a three-stage gadget:
XStream → HSQLDB
connectionInitSqls: The deserialization graph reachesHSQLMetadataStorage$SchemaMismatchException, which carries a liveDataSourcewhoseconnectionInitSqlslist is attacker-controlled. When XStream populates the object, the DataSource is configured with a set of SQL statements.SQL → JSP polyglot: The
SCRIPTcommand writes a query result to the TeamCity webroot as a.jspwsfile. The result row contains a JSP payload that callsRuntime.getRuntime().exec()with the attacker’s command, then deletes its own file.HTTP GET → JSP execution: The attacker requests the dropped
.jspwsURL. TeamCity serves it through the embedded JSP compiler, executing the command as the service account.
The FreeMarker HashAdapter + Commons Collections TiedMapEntry bridge ties the HSQLDB object into the XStream deserialization chain so that simply deserializing the XML is enough to populate and execute the entire sequence.
Attack Vector
- Register a synthetic agent via
POST /app/agents/v1/register(unauthenticated) — returns a session token. - Deliver the crafted XStream XML to
POST /app/agents/v1/commands/error— triggers deserialization, which writes the JSP shell. - Request the dropped
.jspwsfile — TeamCity compiles and executes it, running the attacker’s command.
No credentials, no agent token, no prior access to any repository or build configuration needed.
Impact
Full remote code execution as the TeamCity service account (typically root or a dedicated teamcity user with broad filesystem access). The attacker can read all build logs, source code, artifacts, and secrets managed by TeamCity; modify build configurations to inject backdoors into built artifacts; and pivot to connected systems (source repositories, deployment targets, cloud credentials).
Environment / Lab Setup
A vulnerable TeamCity instance is required. The PoC targets a stock Windows or Linux TeamCity installation with default settings.
| |
Setup Steps
| |
Proof of Concept
See
CVE-2026-63077.pyin this folder — mirrored byte-for-byte from the Rapid7 research repository. The upstream README is preserved asupstream-README.md.
Step-by-Step Reproduction
Deploy a TeamCity instance — a stock Windows or Linux install, version 2023.11–2026.03.
Run the PoC:
Shell script1python3 CVE-2026-63077.py --cmd "id" http://TARGET:8111Verify execution — the command output is not returned to the caller, but the HTTP response token confirms the JSP executed. On a test instance, use a reverse shell or a touch-a-file command to confirm.
Exploit Code
The gadget graph builds an XStream <linked-hash-map> containing three entries:
HSQLMetadataStorage$SchemaMismatchException— carries theDataSourcewithconnectionInitSqlsthat create a table, insert a JSP payload row, andSCRIPTit to the webroot.HashAdapter— FreeMarker bean wrapper bridging the DataSource into the Commons Collections chain.TiedMapEntry— Commons Collections key-value pair whosegetValue()call triggers the full deserialization cascade.
The polyglot JSP payload (embedded in the INSERT statement):
| |
Expected Output
=======================================================================================
Rapid7 Labs - JetBrains TeamCity unauthenticated RCE via agent polling (CVE-2026-63077)
=======================================================================================
[+] Targeting: http://TARGET:8111
[+] Registering session: /app/agents/v1/register returned session XX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[+] Triggering deserialization: /app/agents/v1/commands/error returned HTTP 500
[+] Triggering JSPWS payload: /XXXXXXXXXXXX.jspws returned HTTP 200
[+] Command executed: idDetection and Indicators of Compromise
Remediation
| Action | Detail |
|---|---|
| Patch | Upgrade to TeamCity 2026.03.1 or later. JetBrains published a fix that adds authentication to the agent error-reporting endpoint and restricts the XStream denylist. |
| Workaround | If immediate patching is not possible: block the /app/agents/v1/commands/error endpoint at a reverse proxy; restrict access to the agent port (typically 8111) to known agent IPs only. |
| Verification | Confirm the TeamCity version is 2026.03.1 or later; check that POST /app/agents/v1/commands/error returns 401 when unauthenticated. |
References
Notes
Verified this session by reading the full PoC source (CVE-2026-63077.py, ~470 lines). The script constructs the XStream gadget graph programmatically using only the Python standard library — no third-party dependencies. It registers a synthetic agent session, delivers the deserialization payload, and requests the dropped JSP terminal. The command is configurable via --cmd; the default is notepad.exe (the Rapid7 standard benign demo command). The JSP payload deletes its own file before executing the command and emits a per-run response token only after Runtime.exec() successfully creates the process.
Malware screen — clean. No obfuscated payloads, no remote downloaders, no credential exfiltration, no miner, no unexpected binaries, no setup.py/install-time side effects. The only outbound connection is the attacker’s deliberate --cmd payload; the script itself performs only HTTP requests to the target TeamCity instance. Author is Rapid7 Labs (Stephen Fewer, sfewer-r7 on GitHub) — a well-known security researcher with a long track record of responsible disclosure through Rapid7’s coordinated disclosure process.
Cross-corroborated against the Rapid7 technical analysis blog post: the gadget chain (XStream → HSQLDB → polyglot JSP), the vulnerable endpoints (/register + /commands/error), and the affected version range all match. The CVE is registered in NVD with CVSS 9.8.
| |