TrendMicro

Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise

The ‘.pth’ mechanism: A known risk, accepted

Python’s .pth file processing is a documented feature, not a bug. Files ending in .pth placed in site-packages are processed automatically every time the Python interpreter starts. CPython core developers have discussed this risk, Issues #113659 and #78125, but treated it as a “won’t fix” because restricting .pth execution would break legitimate use cases.

Issue #113659 was addressed, and Python versions 3.8 through 3.13 now skip hidden .pth files, which reduces some risk. Although the broader proposal to deprecate or remove .pth code execution entirely (Issue #78125) remains unresolved, these partial mitigations demonstrate ongoing efforts within the CPython community to balance security concerns with backwards compatibility.

This isn’t the first exploitation: Volexity observed .pth abuse in CVE-2024-3400 exploitation.

The npm track (checkmarx-util-1.0.4) followed an identical pattern but targeted DevSecOps engineers through a fake Checkmarx utility package. It was served directly from attacker-controlled infrastructure at checkmarx.zone rather than the public npm registry, with a postinstall hook triggering automatic execution. Internal timestamps were set to October 26, 1985, the “Back to the Future” date, a deliberate anti-forensic Easter egg from a Western-culture-aware operator.

From one IP to a multi-ecosystem campaign

The GitHub issue gave defenders a starting point. Our analysis began with a single seed IOC, IP address 83.142.209.11, and expanded through five systematic enrichment pivots over 50 minutes, consuming 34 VirusTotal API calls. What emerged was not a single-package compromise but a coordinated, multi-ecosystem supply chain campaign we track as TeamPCP.

Three supply chain tracks, one actor

All three tracks converged on the same encryption scheme (AES-256-CBC + RSA-4096-OAEP), the same credential targets, the same persistence mechanism, and the same C&C infrastructure, confirming a single unified toolchain. The actor embedded their own branding throughout: “TeamPCP” strings in payload code, “tpcp.tar.gz” as the exfiltration archive name, and cultural artifacts like the code comment “ICP y u no radio? ;w;”, an English-language internet-culture reference that would later factor into attribution analysis.

The credentials harvested from Trivy CI/CD runners became the keys to subsequent compromises, each expanding the campaign’s reach:

  • npm (March 20): Less than 24 hours after the Trivy compromise, TeamPCP deployed a self-propagating worm — dubbed CanisterWorm by Aikido researchers — across the npm ecosystem. The worm stole npm tokens from compromised runners, enumerated all packages the tokens had publish access to, and published malicious versions automatically. Twenty-eight packages in the @EmilGroup scope were infected in under 60 seconds. The worm used an Internet Computer Protocol (ICP) canister as its command-and-control dead-drop — the first documented use of ICP for C&C, according to Aikido. ICP canisters cannot be taken down by traditional domain registrar or hosting provider action.
  • Checkmarx KICS (March 23): Using compromised Checkmarx credentials, TeamPCP hijacked all 35 tags (v1 through v2.1.20) of the KICS GitHub Action, an infrastructure-as-code security scanner. Two malicious VS Code extensions were also published to the OpenVSX marketplace. The payload used a new C&C domain (checkmarx[.]zone) but contained the same RSA-4096 public key and tpcp.tar.gz exfiltration naming as the Trivy payload, confirming shared infrastructure.
  • Docker Hub (March 22): Malicious Docker images (aquasec/trivy:0.69.5 and 0.69.6) were pushed directly to Docker Hub using compromised credentials, bypassing the GitHub release process entirely. These images propagated to third-party mirrors including mirror.gcr.io.
  • PyPI — LiteLLM (March 24): The cascade reached LiteLLM when its CI/CD pipeline ran the compromised Trivy as part of its build process. The malicious Trivy code harvested the PYPI_PUBLISH token from the GitHub Actions runner environment. The LiteLLM maintainer confirmed this was the attack vector: the compromise “originated from the trivvy [sic] used in our ci/cd”

Infrastructure: 90 days of preparation for a 48-hour attack

The infrastructure behind TeamPCP reveals disciplined operational planning that contrasts sharply with the eventual campaign detection timeline:

Both C&C nodes, 83.142.209.11 (checkmarx[.]zone) and 46.151.182.203 (LiteLLM[.]cloud), were hosted on AS205759, a bulletproof hosting provider operating under Ghosty Networks LLC / DEMENIN B.V. with a Netherlands/Ukraine jurisdictional gap exploited for abuse reporting friction. JARM TLS fingerprinting revealed identical server configurations across both nodes, a fingerprint inconsistent with commodity nginx and consistent with the AdaptixC2 framework, an open-source Go C&C toolkit.

AdaptixC2’s developer, “RalfHacker,” has been linked to the Russian criminal underground. The framework has been used by an Akira ransomware affiliate, based on infrastructure overlap, though the strength of this attribution link warrants caution.

The kill switch: A YouTube URL as a global “off” switch

One of the campaign’s most operationally notable features was its deactivation mechanism. Both supply chain tracks installed a persistence daemon that polled the C&C server every 50 minutes. Before executing any stage-2 payload, the daemon checked whether the response contained the word “youtube”, if so, execution was silently skipped.

At the time of our analysis, the /raw endpoint was serving a 43-byte YouTube URL. The kill switch was active. Every compromised host with a running persistence daemon had been globally deactivated without requiring individual C&C commands. The choice of “youtube” as the trigger is pragmatic, a YouTube URL naturally contains the string, making the deactivation response appear as benign content if intercepted by network monitoring.

Whether the actor triggered the kill switch because they detected the on-going analysis, completed a harvesting cycle, or wanted to reduce forensic exposure remains an open question. The mechanism demonstrates operational maturity, the ability to globally shut down a campaign with a single server-side change, though this pattern has been observed in other criminal C&C frameworks and is not unique to this campaign.

The bot suppression campaign: Information warfare meets vulnerability disclosure

Within minutes of the GitHub issue being filed, something unusual happened: a wave of comments flooded the thread.

According to community analysis:

  • 121 compromised GitHub accounts activated within minutes of disclosure
  • StepSecurity documented 196+ bot comments flooding the thread, the majority generic praise spam identical to patterns observed in the Trivy compromise
  •  

Flooding the GitHub issue with noise was likely done to delay triage and community response. This is a notable operational TTP; previous supply chain attacks relied on stealth and hoped for slow detection. TeamPCP actively fought disclosure.

Whether this constitutes “information warfare applied to vulnerability disclosure” or automated spam from a botnet operator selling services depends on the actor’s organizational structure, which remains unconfirmed. What’s clear is that the suppression capability was pre-positioned and activated rapidly.

Who is TeamPCP?

Read More HERE