Supply chain attacks are hard. That's not a controversial take. It's something anyone who has worked in software security long enough already knows. The organizations caught in the TeamPCP campaign aren't careless companies staffed by people who don't know better. Trivy is a well-regarded open source scanner maintained by a serious security team. Checkmarx is a mature vendor with a large security organization. Bitwarden is one of the most widely trusted open source password managers in the industry. The fact that any of them were affected is a reminder that supply chain security is an unsolved problem at the industry level, not a sign that any individual team failed the basics.
The credential exposure from these breaches is real and the downstream risk is ongoing. But the "how could a security company let this happen" framing isn't useful... Security companies will always be targets for attackers, whether that’s to brag to fellow criminals, or to target downstream customers through a trusted channel. The more useful question is: what did the attacker actually exploit, and what can any team do to ensure they are not next, even if they aren’t a security company?
The Campaign So Far
TeamPCP began in late February with a methodical scan of public repositories for exploitable GitHub Actions workflows. We were watching carefully. But to briefly recap what happened next: Their initial foothold was a pull_request_target misconfiguration, a well-documented but still-common CI vulnerability, that allowed them to steal a Personal Access Token from the Aqua Security GitHub organization. From there, the campaign expanded in stages.
The Trivy compromise involved a malicious binary pushed alongside legitimate releases, force-pushed commits to 75 GitHub Actions version tags, and credential harvesting at scale across any CI pipeline that referenced those actions. Stolen npm tokens from Trivy were then used to seed CanisterWorm across 50+ npm packages, a self-propagating worm with blockchain-based C2 infrastructure that cannot be taken down via conventional means. Credentials gathered along the way then enabled the first Checkmarx compromise, with all 35 tags of kics-github-action and ast-github-action pointing to malicious commits for several hours.
LiteLLM, which uses Trivy in its CI pipeline, was hit separately. The malware was delivered via a .pth file that executes on every Python interpreter startup, before any import.
That was March, we covered it in a blog the day of the LiteLLM attack. The campaign didn't stop there, and the team responsible were trying to sell the data from the attack, claiming they were burned out.
On April 22, Docker flagged suspicious activity on the official checkmarx/kics Docker Hub repository. Attackers had overwritten existing trusted tags, including v2.1.20, alpine, debian, and latest, and introduced a fake v2.1.21 tag with no corresponding upstream release. The modified images bundled a Golang binary that generated uncensored Infrastructure as Code scan reports, encrypted the results, and exfiltrated them to an attacker-controlled domain impersonating Checkmarx infrastructure. Teams that used KICS to scan Terraform, CloudFormation, or Kubernetes configurations during this window should treat any credentials exposed to those scans as potentially compromised. The Checkmarx Developer Assist and AST-Results VS Code extensions were also found to contain malicious code that silently downloaded and executed a credential-harvesting payload on activation.
Then, the same day, the campaign reached Bitwarden CLI. The compromised package was @bitwarden/cli@2026.4.0, published to npm between 5:57 PM and 7:30 PM ET on April 22. The malicious code, injected into a file called bw1.js, ran on installation and harvested GitHub and npm tokens, SSH keys, environment variables, shell history, and cloud credentials. It encrypted the results and exfiltrated them to the same audit.checkmarx[.]cx domain used in the KICS attack. The attack vector was a compromised GitHub Actions workflow inside Bitwarden's own CI/CD pipeline. The malicious package carried Bitwarden's legitimate branding and metadata without any obvious red flags. Bitwarden confirmed the incident and stated that no end-user vault data was accessed.
The payload uploaded to Bitwarden's workflow shows exactly how the build process was abused. The publish-cli.yml workflow used npm's OIDC token exchange to obtain a publish token, which the attacker used to push the malicious cli-2026.4.0.tgz directly to npm under Bitwarden's verified namespace. We've attached that file below.