Chain Reaction: How One Stolen Token Tore Through Five Ecosystems
好的,我现在需要帮用户总结这篇文章的内容,控制在100字以内。首先,我得仔细阅读文章,抓住主要信息。 文章讲的是TeamPCP活动,这是一个大规模的凭证盗窃活动。攻击者利用Trivy的安全漏洞,窃取了静态凭证,导致五个生态系统被入侵。攻击链从GitHub Actions开始,逐步扩散到npm、Docker Hub、PyPI等多个平台。 关键点在于静态凭证的风险,文章强调了替换静态凭证的重要性,建议使用短生命周期的加密身份认证。同时,发现和替换所有静态凭证是解决问题的关键。 接下来,我需要将这些信息浓缩到100字以内。要确保涵盖攻击过程、影响范围以及解决方案。避免使用复杂的术语,让总结简洁明了。 最后检查字数和内容是否符合要求,确保没有遗漏重要信息。 </think> 文章描述了一次大规模的凭证盗窃活动TeamPCP,攻击者通过Trivy的安全漏洞窃取静态凭证,并利用这些凭证入侵GitHub Actions、npm、Docker Hub、PyPI等多个生态系统。攻击链展示了静态凭证在环境中的持久性和传播性。文章强调了替换静态凭证的重要性,并建议采用短生命周期的加密身份认证来降低风险。 2026-3-26 18:53:59 Author: securityboulevard.com(查看原文) 阅读量:4 收藏

Why Your Static Credentials Are a Ticking Time Bomb

The TeamPCP campaign, one of the largest credential theft campaigns of 2026, began with a compromise in Trivy. A security tool trusted to scan for vulnerabilities and leaked secrets was weaponized against the very environments it was meant to protect. Instead of catching exposed credentials, it was used to extract them.

The last time this happened at this scale was SolarWinds.

The TeamPCP campaign didn’t rely on a zero-day or sophisticated malware. It didn’t require a nation-state capability. It required one thing: a static credential exposed at runtime.

This isn’t a new attack technique, it’s what happens when credentials persist and cascade.

The Chain

On February 27, an attacker exploited a pull_request_target misconfiguration in Trivy’s GitHub Actions workflow. A single pull request, opened and immediately closed, was enough. The workflow fired anyway with elevated privileges, and the attacker extracted a Personal Access Token (PAT) with write access to repository secrets. Aqua Security rotated credentials on March 1, but as often happens in such cases with human-in-the-loop, the rotation was incomplete.

Three weeks later, on March 19, the attacker force-pushed 76 of 77 trivy-action tags to malicious versions and released Trivy v0.69.4 with an embedded credential stealer. The exposure window was four hours. Over 10,000 workflow files referenced trivy-action.

On March 20, CanisterWorm appeared on npm, a self-propagating worm deployed using stolen npm tokens. 66 packages were compromised. On March 22, a Kubernetes wiper with Iran-targeted destruction was deployed, and malicious Trivy images (v0.69.5, v0.69.6) were pushed directly to Docker Hub using compromised registry credentials. On March 23, Checkmarx KICS was compromised (35 tags hijacked), and a LiteLLM maintainer’s PAT was stolen along with the project’s PYPI_PUBLISH token.

On March 24, litellm versions 1.82.7 and 1.82.8 were published to PyPI. Three-stage payload: credential harvester, Kubernetes lateral movement, persistent backdoor. 

The attack was discovered after approximately three hours, not by any scanner or monitoring tool, but because a bug in the attacker’s own malware (possibly AI-generated) caused a fork bomb that crashed a developer’s machine.

As Andrej Karpathy noted: “If the attacker didn’t vibe code this attack, it could have been undetected for many days or weeks.”

The Blast Radius

LiteLLM is everywhere. ~95 million monthly downloads, present in over a third of cloud environments. Its dependency runs straight through theAI agent ecosystem: CrewAI, DSPy, Browser-Use, Mem0, Opik, Instructor, Guardrails, Agno, Camel-AI. 

TeamPCP claimed 54GB of exfiltrated data. Over 1,000 SaaS environments were actively dealing with the threat actor when this came to light.

Five ecosystems compromised in four weeks: GitHub Actions, npm, Docker Hub, PyPI, OpenVSX. All from a single stolen PAT.

The Common Thread

Every escalation in the chain required a static credential sitting in an environment. The PAT in the Trivy runner. The npm tokens on developer machines. The PYPI_PUBLISH token in LiteLLM’s CI configuration. The Docker Hub credentials in the build pipeline. Each step depended on the last.

The security tools did their job. Trivy scanned. KICS checked. The scanners ran green. And behind them, static credentials sat in environment variables, waiting to be read by the next compromised dependency.

“Just Pin It” and Other Incomplete Answers

The default response to a supply chain attack is to harden the supply chain. Pin dependencies. Vault secrets. Rotate more often. All good practices but none of them fix the problem.

Pinning narrows where an attack can enter but it doesn’t change what happens when code is running. TeamPCP force-pushed 76 git tags without changing a single release page. Version tags are mutable pointers, not guarantees.You can pin to a commit SHA or image digest, and you should. But if that code runs in an environment full of static credentials, it still has access to them.

Vaulting secrets just changes where the secret lives. At some point it gets injected into an environment variable for a CI/CD run and it is still a static secret during runtime. The vault only protects at rest, while the environment variable is exposed at execution.

Rotating more frequently reduces the window but not the risk. Miss one and you can get the worst outcome: exposure with false confidence. 

These are layers of defense, not a fix. As long as access is based on possession of a credential, the vulnerability doesn’t go away.

What the Defense Should Look Like

The fix isn’t more scanning, better vaults, or tighter rotations; it’s replacing the credential model entirely. 

Every static credential, whether it is a PAT, an API key, a publish token, or a cloud access key, needs to go. Replace them with a short-lived cryptographic identity based on open standards: SPIFFE, OAuth, OIDC, WIMSE. Identity should be issued just-in-time, scoped to a specific action, and cryptographically bound to the workload that requested it.

Developer machines. The LiteLLM compromise didn’t just hit CI runners. It hit anyone who ran pip install litellm locally. Developer environments are full of static credentials: cloud access keys, npm tokens, git credentials, API keys. TeamPCP scanned over 50 filesystem paths looking for exactly this. The same principle applies here. Anything a developer uses should be short-lived, non-static, and expire after use.

CI/CD pipelines. The PYPI_PUBLISH token that enabled the LiteLLM upload was a static secret stored in GitHub Actions. CI systems should use OIDC to get short-lived credentials scoped to a single run. No static tokens. No secrets injected into environment variables. The runner proves its identity cryptographically, and the authorization is granted for minutes, not months.

Production, staging, and everything in between. The same principle applies across all environments. Workloads authenticate with short-lived identity, not shared secrets. Service-to-service uses mTLS with automatic rotation. If something is compromised, there is nothing durable to reuse.

There’s one prerequisite most teams skip: you can’t replace what you don’t know exists.

Discovery comes first. You can’t replace what you don’t know exists. Credentials are spread across developer machines, CI, staging, and third-party systems. Without a map, you’re guessing. During an incident, that means weeks instead of hours to understand the impact.

The supporting controls still matter:

  • Pin dependencies to immutable references: commit SHAs, image digests
  • Lock down access: branch protection, MFA, least privilege
  • Verify provenance: signed commits, release integrity, SLSA

These reduce exposure. They don’t eliminate it. 

If you do one thing: eliminate static credentials.

That alone would have broken the TeamPCP chain at multiple points. No PAT in the runner, no initial escalation. No publish token, no malicious package. No developer tokens, no spread.

How Defakto Approaches This

Our approach has two parts.

First, discovery.
You need a complete map of every non-human identity: where static credentials exist, what they grant access to, who owns them and what depends on them. Across production, staging, CI/CD, and developer machines. That map tells you where to start and what your blast radius looks like when something breaks.

Second, replacement. Every workload, pipeline, and agent gets a short-lived cryptographically verifiable identity issued at runtime. Credentials expire in minutes, not months, and are bound to the workload using open standards like SPIFFE, OAuth, and OIDC. If something is compromised, there’s nothing durable to reuse.

The chain TeamPCP relied on, where each step exposes the next set of credentials, only works if those credentials persist. Eradicating secrets breaks the chain.

The Larger Pattern

The TeamPCP campaign was sophisticated in its understanding that credentials cascade. Each step exposed the next set of access, across five ecosystems, from a single stolen PAT.

Most supply chain discussions focus on how the attacker got in: the misconfigured workflow, the unverified tag, the missing signature check. These matter but it’s not what made it effective. What made it devastating is that every environment they touched had static credentials waiting to be used somewhere else.

And the fallout is far from over. The 54GB of exfiltrated data includes credentials from CI, developer machines, and production systems across thousands of organizations. Many of those credentials are still valid and could remain valid for weeks, months, or indefinitely, because the organizations that own them either don’t know they were compromised or are afraid to rotate them so they delay. They open tickets. They schedule reviews. And in the meantime, the stolen credentials sit in an attacker’s hands, unlocking systems their owners have not yet thought to check.

That is the long tail of this kind of breach. The initial compromise takes hours. The exposure lasts weeks or months. Every unrotated credential is an open door. Every rotation without context risks breaking something critical.

The industry response has been to manage the problem better, with more scanning, better vaults, and tighter rotation. But all of that assumes static credentials are a given.

They are not. Static credentials were the common thread at every stage of this attack. Eradicating them is the only way to remove the class of risk, not just patch the entry point.

If you’re trying to understand where static credentials exist in your environment and what they expose, we’d welcome the conversation.

The post Chain Reaction: How One Stolen Token Tore Through Five Ecosystems was originally published on Defakto.

*** This is a Security Bloggers Network syndicated blog from Defakto authored by Eli Nesterov. Read the original post at: https://www.defakto.security/blog/chain-reaction-how-one-stolen-token-tore-through-five-ecosystems/


文章来源: https://securityboulevard.com/2026/03/chain-reaction-how-one-stolen-token-tore-through-five-ecosystems/
如有侵权请联系:admin#unsafe.sh