TeamCity as an Initial Access Vector: The JetBrains Cadence AWS Credential Theft

TeamCity as an Initial Access Vector: The JetBrains Cadence AWS Credential Theft

pr0h0
cybersecurityteamcityawsjetbrainsdevsecops
AI Usage (77%)

What the report says happened

The public reporting says attackers reached JetBrains Cadence through an unpatched TeamCity instance and then pulled out AWS credentials. That is the part worth focusing on. A TeamCity foothold is not just “another server compromise”; in a lot of shops, it is the shortest route to the most sensitive material around: build secrets, signing keys, deploy tokens, cloud roles, and the logs that quietly print all of it.

My view is straightforward: if a CI/CD server is exposed and behind on patches, treat it like a production incident in progress. In many environments, it is a more valuable target than the app server itself.

The reported path from TeamCity to Cadence

Based on the report, the rough chain was:

  1. Attackers reached TeamCity.
  2. TeamCity was unpatched.
  3. From there they obtained AWS credentials tied to Cadence-related infrastructure.

That is enough to make the incident serious even without every internal detail. Once AWS credentials are stolen, the attacker does not need to keep working through the original Java app or UI. They can move sideways into storage, compute, secrets managers, and CI/CD itself.

What is confirmed by the public reporting versus what is inferred

CategoryWhat is confirmedWhat is inferred
Entry pointPublic reporting says TeamCity was the initial footholdThe exact exploit path and access method are not public here
ImpactAWS credentials were extractedWhich AWS services were reachable, and how far the access went, is not confirmed in the source seed
ScopeJetBrains Cadence is the named target in the reportWhether the attacker also touched code, artifacts, or deployment pipelines is unknown
RemediationThe report implies patching matteredRotation, IAM cleanup, and server rebuilds would likely be needed, but that is not stated in the seed

That split matters. I do not want to pretend the public seed says more than it does.

Why TeamCity is a high-value foothold

Build servers often sit close to source code, secrets, and cloud roles

TeamCity and similar systems usually have access that app servers do not. They need to fetch private repositories, run deploy jobs, sign artifacts, call package registries, and often assume cloud identities for release steps. That means the blast radius of a compromise is usually bigger than the blast radius of a single web app.

In practice, a build server may have all of the following:

  • repository credentials
  • environment variables containing deploy secrets
  • access to artifact repositories
  • cloud provider keys or role tokens
  • agent workspaces with checked-out source and generated files
  • build logs that accidentally print secrets

That is why CI/CD compromise is so dangerous. It is not just another box on the network. It is where trust gets concentrated.

Why an unpatched CI system can outrank the app server itself

If an attacker gets the application server, they may still need to fight auth, session boundaries, and least-privilege controls to reach anything useful. If they get the CI server, the machine is often already authorized to do the boring but powerful things: read secrets, deploy builds, and talk to cloud APIs.

That is the real asymmetry.

A neglected app server is bad. A neglected CI server can become a secret siphon. In my view, that makes unpatched CI software one of the fastest paths from “internet exposure” to “cloud compromise.”

How AWS credentials usually get exposed in CI/CD environments

Environment variables, build logs, agent access, and artifact leaks

AWS credentials in CI/CD environments usually leak through ordinary operational paths, not exotic malware.

Common places to look:

  • environment variables injected into build steps
  • shell traces that echo export lines
  • build logs that include debug output
  • agent workspaces with copied config files
  • archived artifacts that accidentally contain .env or credential files
  • plugin configs and shared parameters
  • cached files under build directories

A leaked key often starts as a harmless-looking string in a log line. Once you can read the logs, you can often read the secrets.

A quick search in a TeamCity backup or a mounted agent directory can be enough to surface the problem:

rg -n --hidden -S 'AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|aws_secret_access_key|AWS_SESSION_TOKEN' \
  /var/lib/teamcity /opt/teamcity/logs /home/build-agent

A suspicious hit may look like this:

/opt/teamcity/logs/build.log:184: export AWS_ACCESS_KEY_ID=AKIA...REDACTED
/opt/teamcity/logs/build.log:185: export AWS_SECRET_ACCESS_KEY=REDACTED

That alone does not prove abuse. It does prove that a build system has been asked to handle cloud credentials in a place where logs can see them.

What an attacker would look for after landing on a build server

If I were auditing the attacker’s likely next steps, I would expect them to search for:

  • .aws/credentials or profile files
  • CI environment variables
  • service account JSON or token files
  • SSH deploy keys
  • repo access tokens
  • cloud role session data
  • cached secrets in workspace directories
  • scripts that call aws sts assume-role, docker login, or kubectl

That is why the first defensive assumption should be: if the CI server is compromised, any secret it ever handled is suspect.

Reconstructing the likely attack chain

Initial access through the TeamCity exposure

The public report says the TeamCity instance was unpatched. That is enough to support a likely chain: exposed management surface, weakness in the server, then privilege on the CI host or inside the TeamCity process context.

I am intentionally not speculating about the exact vulnerability. The important point is more boring and more useful: unpatched CI software is a standing invitation to attackers because it combines internet exposure with privileged access to downstream systems.

Credential discovery and extraction opportunities

Once inside, the attacker likely had several chances to collect AWS credentials:

  1. Build environment variables
    Many pipelines inject cloud keys directly into the process environment.

  2. Logs
    Debug output, failed deploys, and printed commands can leak both access keys and session tokens.

  3. Agent filesystem
    Agents often write checkout data, cached dependencies, and temporary config files to disk.

  4. Artifacts and archives
    A build artifact can accidentally package a credentials file or .env snapshot.

  5. TeamCity configuration data
    If the instance held build parameters or integration settings, those may have pointed to reusable credentials.

That is the mechanism I would assume until proven otherwise. It is also why “we rotated the key” is not the end of the story.

Why AWS keys are especially dangerous once stolen

AWS access keys are not interesting because they are long strings. They are dangerous because they can become durable programmatic access if they are attached to a user with broad permissions.

Once stolen, a key can be used to:

  • enumerate IAM permissions
  • read secrets from Parameter Store or Secrets Manager
  • access S3 buckets
  • launch compute
  • inspect logs and backups
  • create new credentials or persistence paths, if IAM allows it

A useful first check is to see whether the key was still active and what it touched:

aws iam get-access-key-last-used --access-key-id AKIAEXAMPLE1234567890

Representative output:

{
  "UserName": "ci-deployer",
  "AccessKeyLastUsed": {
    "LastUsedDate": "2026-09-04T21:18:02+00:00",
    "ServiceName": "ec2",
    "Region": "us-east-1"
  }
}

If the access pattern does not match the expected CI workload, treat that as evidence of compromise rather than noise.

What security teams should verify first

Patch status, exposed admin surfaces, and agent inventory

My first pass would be:

  • confirm the TeamCity version
  • check whether the server is internet-facing
  • list every agent and where it runs
  • verify whether administrative endpoints are reachable from untrusted networks
  • review plugin inventory and update history

A small inventory table helps keep the review honest:

CheckWhat you want to knowWhy it matters
TeamCity versionIs it current and supported?Old builds are the easiest initial access path
Internet exposureIs the UI or admin API public?Public exposure multiplies risk
Agent countHow many systems can run builds?Each agent is another secret-processing node
PluginsAre third-party plugins installed?Plugins expand attack surface
Auth settingsSSO, local users, tokens, 2FAWeak auth makes foothold recovery easier

Secret scope, rotation status, and cloud IAM blast radius

Then move to the cloud side:

  • identify every AWS key that TeamCity ever handled
  • check whether keys are long-lived or temporary
  • review IAM policies attached to those identities
  • rotate anything that touched CI secrets
  • inspect CloudTrail or equivalent logs for unusual use

If a CI server held a key with broad IAM permissions, the problem is not just theft. It is overprivilege.

Defensive checks you can run in a lab or on internal systems

Search for leaked credentials in logs, configs, and build histories

If you have authorization to review the environment, start by searching for known secret patterns in logs and workspaces:

rg -n --hidden -S 'AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|aws_secret_access_key|AWS_SESSION_TOKEN|BEGIN PRIVATE KEY' \
  /var/log/teamcity /opt/teamcity /data/teamcity-agent

What I would treat as a finding:

  • access key IDs in logs
  • session tokens in temporary files
  • .env files archived into artifacts
  • plaintext cloud profiles in workspace caches

What I would not treat as proof by itself:

  • a single pattern match without context
  • an old test key in a sandboxed job
  • a key that is obviously redacted or dummy data

Review TeamCity roles, plugins, and authentication settings

A second check is to review what TeamCity users and plugins can do. Look for:

  • admin roles granted too broadly
  • disabled MFA on privileged accounts
  • stale local accounts
  • plugins that can read settings or execute code
  • token-based auth that outlives the people who issued it

If you can query TeamCity through the API, do it from an admin account and keep the output limited to inventory data. Do not try to “prove” compromise by making the system do anything risky.

Validate AWS access keys against expected usage patterns

For AWS, compare observed key usage to normal CI behavior.

Useful commands:

aws iam list-access-keys --user-name ci-deployer
aws iam get-access-key-last-used --access-key-id AKIAEXAMPLE1234567890

Questions to answer:

  • Was the key used from the expected region?
  • Did it touch services the pipeline normally uses?
  • Was it active after rotation should have removed it?
  • Did the key appear in CloudTrail from unfamiliar source IPs or user agents?

That is usually enough to decide whether you have a hygiene issue or an incident.

Hardening steps that actually reduce this risk

Treat CI/CD as production-grade infrastructure

If TeamCity can reach secrets, then TeamCity is production. That means:

  • patch it like production
  • restrict network access like production
  • log it like production
  • back it up like production
  • monitor it like production

A build system should not be “the place where we can be a little lazy because it is just tooling.” That mindset is how tooling becomes the breach path.

Rotate and scope secrets so a single server cannot expose everything

Secret rotation is necessary, but rotation alone is weak if the same server still has broad access.

Better controls:

  • use per-pipeline or per-environment credentials
  • scope IAM policies to one job or one service
  • avoid shared human-plus-machine secrets
  • prefer secret managers over inline variables
  • keep build logs from printing env dumps

Reduce standing access and prefer short-lived cloud credentials

Long-lived AWS keys are the easiest thing for an attacker to reuse. Short-lived credentials raise the cost of theft and limit replay.

Prefer:

  • STS-assumed roles over static keys
  • workload identity federation where possible
  • session durations that match the job, not the quarter
  • tightly bounded IAM policies
  • automatic key revocation paths

What I would prioritize if this were my environment

Fix order: patch, rotate, audit, then tighten privileges

If this were my incident queue, I would do it in this order:

  1. Patch TeamCity or take it offline until patched.
  2. Rotate all credentials the server could reach.
  3. Audit logs, agents, and artifacts for leakage.
  4. Tighten IAM and CI roles so the same mistake is less damaging next time.

That order matters because a clean-looking server with stale credentials is still a compromise waiting to happen.

Why secret rotation without server remediation is incomplete

I do not trust rotation by itself if the original TeamCity exposure is still present. If an attacker still has a path back into CI, they can wait for new secrets to appear, harvest them again, or use the CI system to mint fresh access.

Rotation is cleanup. Remediation is closing the door.

Conclusion: CI/CD compromise is an initial access problem, not just a tooling problem

The reported JetBrains Cadence incident fits a pattern I keep seeing: the real damage comes from the trust a CI server already has. Once an attacker lands there, the path to cloud credentials is usually short and very ordinary.

That is why I would not describe this as “just a TeamCity issue.” It is an initial access problem, a secrets-handling problem, and an IAM design problem all at once.

Further reading: official TeamCity security advisories, AWS IAM best practices, and vendor incident write-ups

Share this post

More posts

Comments