TeamPCP's PyPI Persistence: WAV Steganography in `telnyx` v4.87.x
Just when we thought the supply chain noise was dying down, TeamPCP is back at it. Following their hits on Trivy and litellm, they’ve managed to push two malicious versions of the telnyx package (4.87.1 and 4.87.2) to PyPI this past Friday.
What’s interesting here is the obfuscation method. Instead of just base64 encoding a payload in a setup.py, they hid the credential harvesting logic inside a .wav file. It looks like they are using polyglot techniques—combining a valid (or potentially junk) audio file format with executable code that gets parsed by the package initialization.
If you have telnyx in your environment, you need to verify your versions immediately. A simple pip list check isn't enough for long-term trust, but it works for triage:
pip show telnyx
If you are running 4.87.1 or 4.87.2, treat the environment as compromised. The payload targets credentials, likely scraping environment variables and .aws folders. For those analyzing the artifact, check the file headers of the `.wav` file included in the package. A true audio file will start with `RIFF`, but if you see Python bytecode headers or executable scripts in there, you’ve found the dropper.
with open('malicious.wav', 'rb') as f:
header = f.read(4)
print(f"Header: {header}")
if header != b'RIFF':
print("Suspicious: Not a standard WAV header")
Given that TeamPCP is clearly targeting CI/CD tools and developer utilities now, how is everyone handling open-source package verification in your pipelines? Are we pinning versions enough, or is it time to air-gap internal build servers?
We saw this hit our dev sandbox this morning. The .wav file acts as a loader; the package decodes the audio data or reads the raw bytes to reconstruct the Python script. We're blocking 4.87.x across the board, but this highlights a gap in standard static analysis tools which often skip media files.
For those hunting, I recommend adding a YARA rule to your CI/CD pipeline that scans non-media extensions for Python keywords inside media containers:
yara rule Media_Polyglot_Suspicious { strings: $py = "import os" nocase $exec = "subprocess" nocase condition: uint16(0) == 0x5249 and // RIFF/WAV header filesize < 200KB and $py and $exec }
This is why I'm a huge proponent of pip-audit and pip-compile for every deployment, not just production. We rely heavily on hashed lockfiles. If the hash changes, the build fails.
Run this in your build steps to check for known vulnerabilities:
pip-audit --desc --strict
It won't catch zero-days like this instantly, but it creates a control gate. Once the vulnerability database updates (which is usually fast for high-profile PyPI packages), your pipeline stops deploying the malicious version automatically.
From a pentester perspective, this is a genius persistence mechanism. Most admins see a .wav or .png in a repo and assume it's a benign asset, so they whitelist it in DLP or scanners. I haven't looked at the telnyx payload specifically yet, but if it's anything like the litellm incident, it's probably hooking into sys.path or sitecustomize to ensure the stealer runs on every import. Definitely rotate your API keys if you've pulled this package recently.
Verified Access Required
To maintain the integrity of our intelligence feeds, only verified partners and security professionals can post replies.
Request Access