Cloud Security Office Hours Banner

CircleCI 2023

Step-by-step kill chain mapped to MITRE ATT&CK Cloud, sourced from official post-mortems and primary technical analyses.

December 2022 - January 2023 Critical CI/CD Platform

CircleCI - Malware on an Engineer's Laptop → A Live 2FA-Backed SSO Session Stolen → Production Access → Every Customer Secret Assumed Compromised

On December 16, 2022 malware was deployed on the laptop of a CircleCI engineer. It was not detected by the company's antivirus. What it stole was not a password but a live SSO session cookie - already authenticated, already backed by two-factor authentication - which let the actor impersonate that engineer remotely and escalate into a subset of production systems. CircleCI is a CI/CD platform, so those systems held customers' environment variables, API keys and tokens. A customer flagged suspicious GitHub OAuth activity on December 29; CircleCI began rotating all GitHub OAuth tokens on customers' behalf on December 31, and on January 4, 2023 published an advisory telling every customer to rotate every secret they had stored on the platform. The instruction is what makes this chain worth reading: not "we were breached" but "assume everything you gave us is compromised, and act today."

A session cookie, not a password - 2FA was satisfied and irrelevant
Undetected by the endpoint antivirus in place
Every customer secret on the platform declared compromised
Found by a customer noticing odd GitHub OAuth activity
📄 CircleCI - Incident report for January 4, 2023 ↗ 📄 CircleCI - Security alert and customer guidance ↗
Initial Access - Malware the Antivirus Did Not See
01
On December 16, 2022 information-stealing malware was deployed to an engineer's laptop and went undetected by CircleCI's antivirus software
T1204.002 - User Execution: Malicious File T1027 - Obfuscated Files or Information

CircleCI's report is direct about the detection failure: the malware was not caught by the antivirus deployed on the machine. That is worth stating plainly rather than treating as an aside, because signature-based endpoint protection routinely misses current infostealers - the family is cheap, widely available, and repacked constantly to defeat exactly that. It is the same class of tooling that opened Snowflake, Vercel / Context.ai and Megalodon. Here the machine belonged to an engineer at a company whose product holds other companies' deployment credentials.

Date: December 16, 2022
Target: The laptop of a CircleCI engineer
Detection: None - the deployed antivirus did not flag it
Malware class: Information stealer, the same family behind several other chains here
Why it matters here: That engineer's access reached customers' deployment credentials
InfostealerAV BypassEngineer EndpointT1204.002
🍪 Credential Access - Stealing the Session, Not the Password
02
The malware stole a valid, 2FA-backed SSO session cookie, letting the actor impersonate the engineer without ever knowing a password or facing a second factor
T1539 - Steal Web Session Cookie T1550.004 - Web Session Cookie

This is the mechanism that makes the chain instructive. A session cookie is the artifact issued after authentication succeeds - it is the system's own record that the user proved who they were, including the second factor. Steal it and replay it, and you inherit that proof without repeating any of it. There is no password prompt, no MFA challenge, and no failed login for anyone to alert on. This is the same property that made the Okta HAR file tokens dangerous ten months later, arriving here from an endpoint rather than a support ticket, and it is why "we enforce MFA" and "our sessions cannot be stolen" are unrelated claims.

Stolen: A live SSO session cookie, already backed by 2FA
What it proves: That authentication already succeeded - including the second factor
Bypassed: Password entry, MFA challenge, and any sign-in-based detection
Result: Remote impersonation of the engineer
Same property abused in: The Okta support HAR files, ten months later
Session Cookie Theft2FA IrrelevantToken ReplayT1539
⬆️ Privilege Escalation - Into Production, and Into Everyone's Secrets
03
The impersonated engineer had access to a subset of production systems, where customers' environment variables, API keys and tokens were held
T1552.007 - Unsecured Credentials: Container API

A CI/CD platform is a custodian of other organizations' most sensitive credentials by function: to build and deploy on a customer's behalf it must hold that customer's cloud keys, registry tokens and repository credentials. So an engineer with production access at such a company is, transitively, an engineer with access to thousands of other companies' production environments. CircleCI reported that fewer than five customers experienced confirmed unauthorized access to third-party systems - but the exposure was necessarily assumed across the whole customer base, because the compromised systems held all of it. That gap between "confirmed abused" and "must be assumed compromised" is where the real cost of this incident landed.

Reached: A subset of CircleCI production systems
Held there: Customer environment variables, API keys, and access tokens
Structural point: A CI platform must hold customers' deployment credentials to function
Confirmed downstream abuse: Fewer than five customers
Assumed exposure: The entire customer base
CI/CD CustodianCustomer SecretsTransitive AccessT1552.007
🔍 Detection - A Customer Noticed First
04
On December 29 a customer alerted CircleCI to suspicious GitHub OAuth activity; CircleCI began rotating all customer GitHub OAuth tokens on December 31

Thirteen days elapsed between the malware landing and anyone noticing, and the notice came from outside. That is the same pattern as Okta, where three customers found the intrusion before the vendor, and it is a consistent enough shape across this library to be worth naming as an expectation rather than an anomaly: your monitoring of a vendor's behaviour in your environment is sometimes better than their monitoring of themselves, because you are watching a smaller surface with more context. The response from December 31 onwards was fast and unusually decisive - rotating tokens on customers' behalf rather than waiting for them to act.

December 16: Malware deployed
December 29: A customer reports suspicious GitHub OAuth activity
December 31: CircleCI begins rotating all customer GitHub OAuth tokens itself
January 4: Public security alert and customer guidance
Pattern: Customer-side detection beating vendor-side, again
Customer Detection13 DaysProactive Rotation
🔄 Response - "Rotate Everything," and Whether You Could
05
CircleCI told every customer to rotate every secret stored on the platform - and for many organizations that instruction was the hard part

The advisory was the right call and it landed on organizations in wildly different states of readiness. Rotating every secret in a CI platform means knowing what they all are, what each one authorizes, what breaks when it changes, and having a path to replace it - and most teams discovered they had none of that. Some rotated in hours. Others spent weeks, or quietly did not finish. CircleCI's own remediation was substantial: restricting production access to a smaller group, adding authentication requirements, and deploying MDM and endpoint tooling targeting the specific behaviours used. But the transferable question is the one pointed at the customer, and it is worth answering before it is asked: if a platform you depend on told you today to rotate every secret you have given it, how long would that take?

Instruction: Rotate every secret stored on the platform
Prerequisite most lacked: An inventory of what those secrets were and what they authorized
CircleCI remediation: Narrowed production access, added authentication requirements, deployed MDM and endpoint detection
The question to answer in advance: How long would a full rotation take you?
Mass RotationSecret InventoryReadiness

🛡 How to Defend Against This Chain

Bind sessions to a device, so a stolen cookie is useless elsewhere. The whole intrusion rests on a portable session. Where your identity provider supports it, bind tokens to device or network context, shorten session lifetimes sharply for privileged roles, and require re-authentication for sensitive actions. MFA at login does nothing about a session stolen after login, which is the specific gap this chain demonstrates.
Assume endpoint antivirus will miss the stealer, and layer accordingly. It did here. Use EDR with behavioural detection rather than signatures alone, restrict which machines can reach production at all, and treat any engineer endpoint with production access as a system requiring the same hardening as a server - because functionally it is one.
Build the secret inventory before someone tells you to rotate. Know every secret held by every third-party platform, what it authorizes, who owns it, and the command that rotates it. Then rehearse a full rotation. This is the single control that separated the organizations that handled this in an afternoon from the ones that took weeks, and it is entirely within your gift.
Use short-lived, federated credentials in CI instead of stored static secrets. The stolen material was valuable because it was long-lived and stored. OIDC federation between your CI provider and your cloud accounts means no durable cloud credential sits on the platform at all - the job mints one per run, scoped and expiring in minutes. That converts "rotate everything" into a non-event.
Monitor what your vendors do inside your environment. A customer caught this by noticing unusual GitHub OAuth activity attributable to CircleCI. Alert on third-party integration behaviour in your own logs - unusual repository access, token use from new locations, activity outside normal build windows - because you may well see it before the vendor does.
Scope the CI platform's access to the minimum, per project. Broad organization-wide OAuth grants to a CI provider mean one compromise reaches everything. Grant repository access per project, restrict which secrets each pipeline can read, and separate production deployment credentials from build credentials so a single custodian never holds the whole set.

Related defense topics