Executive Summary
Malicious releases of telnyx (4.87.1, 4.87.2) were published to PyPI in a supply chain compromise of the official Telnyx Python SDK, a widely-used communications platform library.
The payload executes at import time, drops a persistent executable into the Windows Startup folder disguised as msbuild.exe, and retrieves an XOR-encrypted binary hidden inside a WAV audio file fetched from a remote C2. On non-Windows systems, a detached Python subprocess executes a secondary base64-encoded payload. The legitimate SDK symbols are re-exported to avoid raising suspicion in developer environments.

Key Judgments
Is this a typosquat? No. This is a compromise of the official
telnyxpackage, not an impersonator.What is unique? The use of WAV steganography to deliver the final payload is an uncommon evasion technique in PyPI malware.
Who is at risk? Any developer or CI pipeline that ran
pip install telnyxor upgraded to 4.87.1/4.87.2 during the exposure window.Was this preventable? Yes, with behavioural diff tooling that flags install-time execution, outbound beaconing, and obfuscated strings in new releases.
Who is TeamPCP?
This compromise is the latest in an escalating campaign by TeamPCP (also tracked as PCPcat, ShellForce, CipherForce), a threat actor group targeting cloud-native infrastructure and developer tooling since late 2025. Their playbook is consistent: compromise one target, harvest credentials, and chain forward into the next.
Timeline
Date | Event | Detail |
|---|---|---|
Feb 27 | Trivy initial compromise | TeamPCP exploits a GitHub Actions misconfiguration to steal a service account PAT |
Mar 1 | Aqua disclosure | Credentials rotated, but a write-access token survives |
Mar 19 | Trivy supply chain attack | Malicious tags force-pushed across |
Mar 22 | Secondary Docker push | Malicious images v0.69.5 and v0.69.6 pushed to Docker Hub. C2 infrastructure goes active |
Mar 23-24 | KICS compromised | Checkmarx OpenVSX extension hijacked via stolen credentials |
Mar 24 | LiteLLM compromised | PyPI versions 1.82.7, 1.82.8 published using tokens harvested from Trivy CI/CD. C2 uses Telnyx infrastructure |
Mar 27 | Telnyx SDK compromised | Ossprey detects malicious PyPI versions 4.87.1, 4.87.2 - this post |
The pattern is clear: each compromise feeds credentials into the next. Trivy’s CI/CD exposed tokens for LiteLLM. LiteLLM’s infrastructure overlaps with Telnyx. This is not a one-off incident - it is a cascading supply chain campaign, and it is still developing.
For our full analysis of the Trivy incident, see our earlier post: Trivy Supply Chain Attack
Technical Breakdown
Execution Vector
The malicious code is injected into the package entry point and runs at import time via calls to Setup() and FetchAudio() appended after the legitimate SDK exports.
String Obfuscation
All sensitive strings are base64-encoded and decoded at runtime via a _d() helper function, bypassing naive string-based static analysis.
Encoded | Decoded |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Windows Dropper - Setup()
Triggers only on Windows (os.name == 'nt'). The routine:
Targets the Startup folder for persistence on every user login, dropping a payload named
msbuild.exeto masquerade as a legitimate Microsoft binary:
Anti-reinfection lock: Writes a hidden
.lockfile viaattrib +h. If the lock file is under 12 hours old (43,200 seconds), the routine exits - a basic sandbox and re-execution deterrent.C2 retrieval: Fetches
hangup.wavfromhxxp://83[.]142[.]209[.]203:8080/hangup.wavusing a spoofedMozilla/5.0User-Agent to blend with browser traffic. The payload is extracted via WAV steganography (see below).Silent execution: The decrypted binary is launched with
creationflags=0x08000000(CREATE_NO_WINDOW), leaving no visible window.Cleanup: The temporary
.tmpfile is deleted after extraction.
WAV Steganography - Hiding an Executable in Audio
The standout technique in this sample - and the reason for the post title - is the use of audio steganography to deliver the final payload. 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.
The file hangup.wav is a structurally valid WAV container. It will open in an audio player without error. But the audio frame data is not sound - it is a base64-encoded, XOR-encrypted PE executable.
The extraction routine uses Python’s built-in wave module:
Step by step:
w.readframes(w.getnframes())reads the raw audio sample data from all frames in the WAV filebase64.b64decode()decodes the frame bytes from base64, revealing an encrypted blobThe first 8 bytes (
s) are split off as the XOR keyThe remaining bytes (
m) are the ciphertextEach byte of the ciphertext is XORed with the corresponding key byte (cycling every 8 bytes) to produce the final PE executable
Why this matters:
Network evasion: The HTTP response carries a valid
.wavfile with an audio MIME type. Content-type inspection, proxy filters, and basic DPI will not flag itStatic analysis resistance: The payload never exists in plaintext on disk until the final write. The WAV file itself looks benign
Low tooling overhead: The entire decryption chain uses only Python standard library modules (
wave,base64) - no third-party dependencies that might raise suspicionDual purpose naming: The filename
hangup.wavreinforces the illusion that this is a legitimate audio asset, particularly given that Telnyx is a communications/telephony platform
The C2 server at 83[.]142[.]209[.]203:8080 is now offline. We were unable to retrieve the WAV file for further analysis of the embedded executable.
Non-Windows Payload - FetchAudio()
On Linux and macOS, a fully detached subprocess executes a base64-encoded Python payload:
The _p variable contains the secondary payload and was not included in the analysed sample. Full package extraction is required for complete analysis.
SDK Masquerade
Legitimate SDK symbols are re-exported after the malicious routines run, making the package appear fully functional to developers who spot-check imports.
OS Targeting
Primary focus is Windows developer and CI environments via the Startup dropper. Linux and macOS systems receive a secondary Python-based payload. Both paths activate at import time with no user interaction required.
What Should You Do
Triage & Contain - Audit
pip freezeandrequirements.txtacross all environments. Iftelnyx==4.87.1ortelnyx==4.87.2is present, treat the environment as compromised. Pin to a known-good prior version (4.86.x or earlier) and rebuild images.Hunt for the Dropper - Check for
msbuild.exein%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\. This is never a legitimate location for msbuild. Also check for the accompanying.lockand.tmpfiles.Rotate Credentials - Any environment where the affected versions were imported must have credentials rotated, including but not limited to:
Telnyx API keys
Any secrets accessible to the Python process at runtime
Cloud credentials (AWS/Azure/GCP) if present in the environment
CI/CD secrets and tokens
Block the C2 - Firewall
83[.]142[.]209[.]203immediately and hunt for outbound HTTP connections to port 8080 at this IP across your estate.Report - Notify PyPI security at security@pypi.org. Notify Telnyx directly so they can issue an advisory and publish a clean release.
Strengthen Publisher Hygiene - Enforce MFA on PyPI accounts, use scoped short-lived publish tokens, and run behavioural diff tooling on new releases before they reach consumers.
Affected Versions
Package | Version(s) |
|---|---|
telnyx | 4.87.1, 4.87.2 |
Pin to 4.86.x or earlier until Telnyx confirms a clean release.
IOCs
Affected Package:
telnyxv4.87.1, v4.87.2C2 Server:
83[.]142[.]209[.]203:8080C2 Resource:
hxxp://83[.]142[.]209[.]203:8080/hangup.wavDropped File:
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exeLock File:
...Startup\msbuild.exe.lockTemp File:
...Startup\msbuild.exe.tmpSpoofed User-Agent:
Mozilla/5.0
SHA-256 Hashes (Malicious Artifacts)
telnyx-4.87.1-py3-none-any.whl-7321caa303fe96ded0492c747d2f353c4f7d17185656fe292ab0a59e2bd0b8d9telnyx-4.87.2-py3-none-any.whl-cd08115806662469bbedec4b03f8427b97c8a4b3bc1442dc18b72b4e19395fe3
MITRE ATT&CK
ID | Technique |
|---|---|
Supply Chain Compromise: Compromise Software Supply Chain | |
Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder | |
Obfuscated Files or Information | |
Masquerading: Match Legitimate Name or Location | |
Application Layer Protocol: Web Protocols | |
Obfuscated Files or Information: Steganography | |
Command and Scripting Interpreter: Python |
Citations and Acknowledgements

Real World Attacks

Trivy Supply Chain Attack and CanisterWorm: Were You Hit?

Mar 23, 2026
Real World Attacks

NPM Package @Ctrl/Tinycolor Compromised: Shai Hulud Malware Targets Secrets and Persistence

Sep 16, 2025
Real World Attacks

Nx Package Compromise: ‘s1ngularity’ Malware Raids Developer Secrets

Aug 27, 2025
