The ctx PyPI Package Hijack

Updated 5 Oct 2026 · Incident date 14 May 2022 · PyPI

Packagectx 0.1.2 (2014) -> ctx 0.1.2 re-upload / 0.2.2 / 0.2.6 (May 2022)
Filenot named in any advisory; the package's single Ctx module

The PyPI package ctx was hijacked in May 2022. Versions 0.2.2 and 0.2.6 carried code that stole environment variables, and Sonatype reports that the old 0.1.2 release was replaced with malicious code as well.

The last real release was 0.1.2 on 19 December 2014. The bad code sent your environment variables, base64 encoded, to a server on Heroku.

What happened

An attacker took control of the ctx package on PyPI. Sonatype reports that the compromise was discovered on 24 May 2022, and that version 0.1.2 was replaced on the registry on 21 May 2022. The GitHub advisory gives the compromise period as 14 to 24 May 2022.

The GitHub advisory says the bad code collected os.environ.items() when a Ctx object was created. It encoded the result in base64 and sent it to a Heroku application endpoint. Environment variables often hold cloud keys, passwords and API tokens.

Sonatype also reports a PHP library, phpass, that carried the same payload. The sources I fetched do not explain how the attacker gained control of the packages.

Affected versions

The GitHub advisory marks ctx versions up to 0.1.4 as vulnerable and lists no patched version. Sonatype names these versions.

The package was removed from PyPI. Because the advisory lists no patched release, stop depending on ctx unless you have verified the source.

Indicators of compromise

How to check

Check whether ctx is installed.

pip show ctx

If it is present, search the installed files for the exfiltration host. The command does not import the package.

pip show -f ctx | head -20; grep -rn "herokuapp" "$(pip show ctx | awk '/^Location/{print $2}')/ctx"

Search your lockfiles for the package.

grep -rniE "^ctx(==|$)" . --include=requirements*.txt --include=*.lock

What to do now

  1. Uninstall ctx and remove it from your requirements files.
  2. If you installed it between 14 and 24 May 2022, rotate every password, API key and cloud credential that was in the environment.
  3. Audit your cloud accounts for use of those credentials.
  4. Check your PHP projects for the phpass library from the affected fork.
  5. Pin dependencies with hashes, so a replaced release fails to install.

Vigilance compares the version you trust with a new one and reports the file that gained a new capability. The ctx module gained environment reading and an outbound post. See all attacks.

What Vigilance showed

Vigilance compares the version you trust with the new one and names the file that gained a new capability. The block below is rebuilt from the public reports in the words Vigilance prints. It is not a captured scan, because the malicious release is not redistributed.

vigi diff --old ctx-prev --new ctx-current
files scanned: 9

HEADS UP  1 file can now do things the old version could not. The rest changed and gained nothing.

CHANGED    setup.py
           It now downloads from the internet and reads saved passwords and access keys. It did not before.

Frequently asked questions

What happened to the ctx PyPI package?

The package was hijacked in May 2022. Bad releases read environment variables and sent them, base64 encoded, to a Heroku site run by the attacker.

How do I check if I installed the malicious ctx package?

Run pip show ctx. If it is installed, search its files for herokuapp and rotate any credentials that were in the environment if you installed it between 14 and 24 May 2022.

Sources

  1. github.com/advisories/GHSA-4g82-3jcr-q52w
  2. sonatype.com/blog/pypi-package-ctx-compromised-are-you-at-risk

More supply chain attacks

All 111 attacks in the library · What is a supply chain attack? · How to prevent supply chain attacks

Check the next update before you install it

Vigilance compares the version you trust with the new one. It names the one file that can now do something it could not do before.

Start Free