Ad
Threats

TeamPCP compromises Telnyx SDK on PyPI, hides credential stealer inside WAV audio files

Artem Safonov
By Artem Safonov , Threat Analyst
TeamPCP compromises Telnyx SDK on PyPI, hides credential stealer inside WAV audio files
Cover © Anonhaven

TeamPCP hit the Telnyx Python SDK on March 27, 2026. The group published two malicious PyPI versions (4.87.1 and 4.87.2) hiding a credential stealer inside .WAV audio files, three days after its LiteLLM attack. The malicious code was live for roughly six and a half hours (03:51 to 10:13 UTC) before PyPI quarantined it. Telnyx has 790,000 monthly downloads and both versions are now quarantined.

Version 4.87.1 was a misfire. A single-character typo (Setup() instead of setup()) caused a NameError that killed the payload on import. Neither the Windows nor the Linux attack path ever executed. Sixteen minutes later, the attacker pushed 4.87.2 with the fix.

All malicious code in 4.87.2 lives in telnyx/_client.py, documented in GitHub issue #235. The legitimate SDK still works normally. The stealer runs alongside it, not instead of it.

Side-by-side diff of the _client.py header. Left: clean v4.87.0 from GitHub (4 lines of imports). Right: malicious v4.87.2 from PyPI (11 lines of imports). Source: Endor Labs.

Rather than hosting a raw executable or a base64 blob on the C2 (both of which are trivially flagged by network inspection and EDR), the attacker wraps the payload inside a .WAV file.

— Ossprey Security

On Windows, the malware downloads hangup.wav from 83.142.209[.]203:8080. It extracts a native executable from the audio frames using the same steganography technique and drops it into the Startup folder as msbuild.exe. A hidden lock file (msbuild.exe.lock) with a 12-hour cooldown prevents repeated downloads. The binary launches with CREATE_NO_WINDOW so no console appears.

Linux and macOS get a different chain. The malware spawns a detached subprocess (start_new_session=True) that survives even if the parent process exits.

It fetches ringtone.wav (23,724 bytes in Endor Labs' network capture) and extracts the payload from audio frames. The extraction uses base64 decode and XOR decryption with the first eight bytes as key. Out comes a 332-line credential harvester.

The strategic split is clear. Windows gets persistence: a binary in the Startup folder that survives reboots, providing the threat actor with long-term, repeatable access. Linux/macOS gets smash-and-grab: a single, high-speed data harvesting operation that collects everything of value and exfiltrates it immediately, then vanishes.

— Socket

The harvester is thorough. It sweeps SSH keys, AWS/GCP/Azure credentials, Kubernetes configs, Docker tokens, and database passwords. It grabs cryptocurrency wallets, TLS certificates, .env files six directories deep, and shell histories for bash, zsh, MySQL, PostgreSQL, and Redis CLI. It also reads /etc/passwd, /etc/shadow, and authentication logs.

If AWS credentials exist, the harvester actively calls cloud APIs. It requests an IMDSv2 token, enumerates IAM roles, retrieves temporary security credentials from Secrets Manager, and queries SSM Parameter Store. The AWS SigV4 signing routine is identical to the one Endor Labs found in the LiteLLM payload.

Kubernetes clusters get hit too. If a service account token exists, the malware dumps all secrets across all namespaces and deploys privileged pods to every node in kube-system. Each pod mounts the host root filesystem at /host with hostPID, hostNetwork, and privileged: True, then chroots into the host to install persistence.

Exfiltration uses hybrid encryption. Collected data is encrypted with AES-256-CBC. The session key is wrapped with a hardcoded RSA-4096 public key using OAEP padding and bundled as tpcp.tar.gz. The archive is POSTed to 83.142.209[.]203:8080 with header X-Filename: tpcp.tar.gz.

That RSA-4096 key is the attribution smoking gun. Endor Labs confirmed it is byte-for-byte identical to the key used in the LiteLLM compromise. The keyspace is 2^4096, and a false flag using this key would be self-defeating since the attacker could not decrypt the stolen data. Endor Labs published the PEM and DER hashes for independent verification.

The RSA-4096 public key from the Telnyx payload (left) and the LiteLLM payload (right) are byte-for-byte identical. Source: Endor Labs.

We believe the most likely vector is the litellm compromise itself. TeamPCP's harvester swept environment variables, .env files, and shell histories from every system that imported litellm. If any developer or CI pipeline had both litellm installed and access to the telnyx PyPI token, that token was already in TeamPCP's hands.

— Kiran Raj and Rachana Misal, Endor Labs

Telnyx used a long-lived PyPI API token rather than OIDC Trusted Publishers for releases. No GitHub commits, tags, or releases exist for versions 4.87.1 or 4.87.2. The attacker bypassed the automated release pipeline entirely and published with a stolen token.

The package footprint shrank 87% compared to LiteLLM. LiteLLM shipped a 34,460-character monolith inline, but Telnyx carries only 4,428 characters as a thin dropper. The real harvester, K8s lateral movement, and cloud exploitation all live on the C2 inside the WAV file.

Persistence artifacts have been renamed to dodge detection rules from the LiteLLM disclosure. The new service is audiomon.service ("Audio Controller"), replacing sysmon.service. The implant polls the C2 every 45 to 55 minutes (jittered, up from a fixed 50) for new WAV payloads. If the response contains "youtube.com", the implant goes dormant.

The audiomon.service unit file from Telnyx (right) compared with sysmon.service from LiteLLM (left). Same polling logic, renamed artifacts. Source: Endor Labs.

The target selection across this campaign focuses on tools with elevated access to automated pipelines: a container scanner (Trivy), an infrastructure scanning tool (KICS), and an AI model routing library (litellm). Each of these tools requires broad read access to the systems it operates on (credentials, configs, environment variables) by design.

— Snyk

The campaign now spans five confirmed targets. Trivy and KICS fell through GitHub Actions. LiteLLM (97 million monthly downloads) through a stolen PyPI token from Trivy. Telnyx through a token harvested from LiteLLM.

Docker Hub, npm (66+ packages via the CanisterWorm), and Open VSX round out the campaign footprint.

TeamPCP has announced collaborations with LAPSUS$ and Vect, an emerging ransomware group tracked by Halcyon. Henrik Plate, head of security research at Endor Labs, noted the group harvested a large volume of credentials across recent attacks. Teaming up allows faster exploitation before victims complete remediation. If operational, stolen build pipeline tokens provide direct paths from supply chain compromise to ransomware deployment.

This puts a spotlight on anything in CI/CD environments that isn't locked down. Security scanners, IDE extensions, build tooling, and execution environments are granted broad access because they're expected to need it. When attackers are targeting the tools themselves, anything running in the pipeline has to be treated as a potential entry point.

— Socket

If you installed telnyx==4.87.1 or telnyx==4.87.2, assume full environment compromise. Downgrade to version 4.87.0, rotate all credentials, and check for persistence artifacts.

On Linux, check for ~/.config/audiomon/audiomon.py, audiomon.service, and /tmp/.initd_state. On Windows, check the Startup folder for msbuild.exe and the hidden msbuild.exe.lock. In Kubernetes, look for node-setup-* pods in kube-system. Block the C2 IP 83.142.209[.]203 at the perimeter. Any match means full credential rotation.

Have a story? Become a contributor.

We work with independent researchers and cybersecurity professionals. Send us a tip or submit your article for editorial review.

Questions on the topic

Was the Telnyx Python SDK compromised?
TeamPCP published malicious Telnyx versions 4.87.1 and 4.87.2 to PyPI on March 27, 2026, hiding a credential stealer inside WAV audio files. Downgrade to 4.87.0 and rotate all secrets.