What Happened
TeamPCP compromised the Checkmarx Jenkins AST plugin in a second supply chain attack, using credentials obtained from an earlier breach. The attackers gained write access to the plugin's GitHub repository and pushed malicious code to production. Checkmarx released version 2.0.13-848.v76e89de8a_053 to remediate the compromise. TeamPCP renamed the repository to "Checkmarx-Fully-Hacked-by-TeamPCP-and-Their-Customers-Should-Cancel-Now," highlighting the severity of the credential management failure and the reputational impact of incomplete remediation.
Timeline
The timeline reveals a critical window where credential rotation should have occurred but didn't:
- Initial breach: TeamPCP compromised Checkmarx infrastructure and exfiltrated credentials, including GitHub access tokens.
- First attack: Attackers used stolen credentials to compromise the KICS project.
- Incomplete remediation: Checkmarx responded to the KICS incident but did not rotate all credentials exposed in the initial breach.
- Second attack: TeamPCP used the same credential set to compromise the Jenkins AST plugin repository, pushing malicious code to production users.
- Public disclosure: The repository defacement made the scope of the credential management failure visible to customers and the broader security community.
Which Controls Failed or Were Missing
This incident maps to multiple control failures across credential lifecycle management and incident response:
Credential inventory and tracking: Checkmarx did not maintain a complete inventory of where the compromised credentials had access. When credentials are stolen, you need to know every system, repository, and service they can touch. The attackers knew the access scope better than the defenders did.
Post-incident credential rotation: After the initial breach, the team rotated some credentials but missed the GitHub tokens that granted write access to the Jenkins plugin repository. This is the core failure—partial remediation that left attack paths open.
Privileged access management: The compromised credentials had write access to production repositories. This level of access should require additional controls: time-limited tokens, approval workflows for production changes, or automated revocation on suspicious activity.
Supply chain integrity verification: The malicious code reached users because the build and release pipeline trusted commits based solely on repository access. No secondary verification caught the unauthorized changes before distribution.
Detection capabilities: The time between the malicious commit and public discovery suggests monitoring gaps. Changes to production plugin code should trigger immediate review, especially during an active incident response.
What the Standards Require
PCI DSS v4.0.1 Requirement 8.6.3 mandates that passwords and passphrases for interactive logins be changed at least once every 90 days, and immediately upon suspicion of compromise. While this requirement focuses on interactive passwords, the principle extends to API tokens and service credentials—the moment you suspect exposure, rotation is not optional.
ISO/IEC 27001:2022 Control 5.17 (Authentication information) requires that allocation and management of authentication information be controlled, including revocation when no longer required or when compromised. The control explicitly states that emergency revocation procedures must exist. Checkmarx had the procedure (they rotated some credentials) but failed the completeness test.
NIST 800-53 Rev 5 IA-5(1) (Authenticator Management | Password-Based Authentication) requires organizations to change authenticators when there is evidence of compromise. The guidance notes emphasize that partial rotation creates residual risk—exactly what happened here.
SOC 2 Type II CC6.1 (Logical and Physical Access Controls) requires that the entity implements logical access security measures to protect against threats from sources outside its system boundaries. This includes credential management processes that prevent unauthorized access. Auditors examining this incident would flag the gap between the first attack and the credential rotation scope as a control deficiency.
Lessons and Action Items for Your Team
Build a credential dependency map now: Document every service account, API token, and automation credential in your environment. For each credential, list every system it can access. When you respond to a breach, this map tells you what to rotate. Without it, you're guessing. Tools like secret scanning (GitHub Advanced Security, GitGuardian, TruffleHog) can help discover credentials in code, but you need a source-of-truth inventory for operational credentials.
Rotate everything in the blast radius: After a credential compromise, rotate all credentials that could have been exposed—not just the ones you saw the attacker use. If they had access to your secrets management system, rotate every secret in it. If they had access to a CI/CD pipeline, rotate every credential that pipeline uses. Assume the attacker has better visibility into your credential topology than you do.
Implement time-limited tokens: Service credentials for production systems should expire automatically. GitHub supports fine-grained personal access tokens with expiration dates. AWS IAM supports temporary credentials through STS. Azure AD offers time-limited service principal credentials. Set maximum lifetimes (30-90 days) and force regeneration. This contains the damage window when credentials leak.
Add verification layers to your supply chain: Code signing, reproducible builds, and automated integrity checks create defense in depth. For plugins and packages you publish, implement a signing process that requires credentials separate from repository write access. For packages you consume, verify signatures and checksums before deployment.
Monitor production repositories during incidents: When you're responding to a breach, increase monitoring on all production code repositories. Alert on any commit, especially outside business hours. Alert on permission changes. Alert on new contributors. During an active incident, assume the attacker will attempt persistence and watch for it.
Test your incident response completeness: After you remediate an incident, have a second team review the scope. Did you rotate all credentials in the blast radius? Did you close all attack paths the adversary used? Did you verify that detection gaps are closed? The second compromise happened because the first response was incomplete. That's a process failure, not a technical one.
The Jenkins plugin compromise wasn't sophisticated. TeamPCP used credentials Checkmarx already knew were compromised. Your incident response procedures should make this impossible—when credentials are exposed, rotation must be comprehensive, immediate, and verified. Anything less leaves the door open for exactly this outcome.



