Yaamlabs

Threat intel

Three malicious PyPI packages and when their code runs

reqparser, tego-managed-agents-test and sherpy ran malware on import, on install and on use. How each trigger works, how to check, and the pip controls that help.

On September 25, three malicious Python packages were reported to OSV (Open Source Vulnerabilities, Google's open advisory database) and have since been removed from PyPI, the Python Package Index. Each one starts its payload at a different moment. reqparser 1.0.0 and 1.0.1 (MAL-2026-17181) runs an infostealer as soon as it is imported. tego-managed-agents-test 0.1.0 (MAL-2026-17183) sends the whole process environment to a remote server during pip install. sherpy 0.1.0 and 0.1.1 (MAL-2026-17188) copies Chrome extension and Telegram files when its code is called. If any of these names appears in a lockfile, a CI (continuous integration) log or a developer's shell history, treat the secrets on that machine as exposed.

None of the three made the news. They surfaced in an automated sweep of OSV data by the open source compromised-packages-check project, whose September 26 update added 30 new malicious entries, 27 on npm and 3 on PyPI. Its previous sweep, four days earlier, added 36. At that pace, a team that installs small, unfamiliar packages without checks is exposed every week, whether or not a large incident is in the headlines.

How it works: install, import and use

A PyPI release ships as a wheel, a zip of files ready to copy into place, or as a source distribution (sdist), a .tar.gz that has to be built first. pip cannot install an sdist directly. It calls the build backend the package names, usually setuptools, to build a wheel, and for a classic project that means running the package's setup.py as ordinary Python, with your user account's permissions and your shell's environment variables.

setup.py can pass cmdclass={"install": CustomInstall} to setup(), which swaps setuptools' install command for a subclass. When setuptools builds the wheel, its bdist_wheel command runs build and then install into a staging directory, so the subclass's run() method executes in the middle of pip install. Nobody has imported anything yet. Datadog's GuardDog scanner has a rule for exactly this pattern, cmd-overwrite.

That is how tego-managed-agents-test works. Its advisory lists a single file, the sdist tego_managed_agents_test-0.1.0.tar.gz, with setup.py as the evidence. Amazon Inspector's analysis says the custom install command serialises dict(os.environ) to JSON, POSTs it to https://gateway.tego.security and silently swallows any error, so the install looks normal. On a developer laptop or CI runner, that environment commonly holds AWS_ACCESS_KEY_ID, GITHUB_TOKEN, NPM_TOKEN and database passwords.

Import time is simpler. Python executes a module's top-level statements the first time it is imported, and for a package that module is __init__.py. A line such as import reqparser in a script or test is enough; no function has to be called. According to the advisory, reqparser starts an infostealer on import that takes cryptocurrency wallet and browser data, logs keystrokes, sets up persistence, installs further malware and checks whether it is running in a sandbox. Its listed indicators are a Dropbox link to a file named VapeInjector.exe and a Discord webhook.

sherpy waits until its code is used, and the malicious logic sits in a native extension, a compiled .so or .pyd module, so a reviewer reading the Python source sees little. The advisory says it exfiltrates Chrome extension files, likely aimed at cryptocurrency wallet extensions, and "sensitive Telegram files".

One common assumption does not hold: pip install --no-deps only skips the named package's dependencies. The package's own setup.py still runs at install and its __init__.py still runs at import.

What attackers are doing

The OSV records were published on September 25 at 06:00 UTC for reqparser, 10:39 for tego-managed-agents-test and 21:13 for sherpy, all credited to analyst Kamil Mańkowski (kam193); Amazon Inspector independently reported tego-managed-agents-test that afternoon. As of September 28 all three projects return "not found" on PyPI. No source gives download counts or names a victim.

Malicious packages usually reach victims through typosquatting, a name one keystroke away from a popular package, or dependency confusion, a public package that shares a name with a company's internal one so the installer fetches the public copy. None of the three advisories labels these packages as either. reqparser sounds like request and requirements parsing tools, but no source says it copied a specific one. tego-managed-agents-test ends in "-test", and the advisories do not attribute it to any organisation or say why it was published; both analysts classify it as malicious on behaviour alone.

The npm side of the same sweep fits the usual pattern more closely: mostly dependency confusion and typosquats, including packages impersonating Epic Games, Deutsche Bank and Airbnb, plus three new suspicious scopes, @airbnb-extended/, @nubjs/ and @digift/. PyPI remains the smaller target in this data: 5 of the 66 entries across the two sweeps.

What to do

Check first. Search requirements*.txt, poetry.lock, uv.lock and Pipfile.lock across your repositories for the three names, run pip show reqparser sherpy tego-managed-agents-test in each virtual environment and container image, and search CI logs for the names. osv-scanner scan -r . does the lockfile part in one pass: OSV-Scanner queries the OSV API, which returns these MAL advisory IDs for the affected versions.

If you find one:

  1. For reqparser, rebuild the machine. The advisory says it persists and installs more malware, so uninstalling the package is not enough.
  2. For tego-managed-agents-test, rotate every secret that was in the environment of the shell or CI job that installed it, and search DNS and proxy logs for gateway.tego.security.
  3. For sherpy, move funds from any wallet extension in that Chrome profile to a new wallet created on a clean device, and in Telegram use Settings, Devices, Terminate All Other Sessions.

For all three, search egress logs for connections to discord.com/api/webhooks/ and Dropbox downloads from build hosts, which have little reason to make either.

Then make the next one harder to install:

  • Hash-pinned lockfiles. Generate requirements.txt with pip-compile --generate-hashes or uv pip compile --generate-hashes, and install with pip install --require-hashes -r requirements.txt. CI then installs only files someone committed, so a new package or a swapped file cannot slip in unnoticed. It does not vet a package you add yourself.
  • Wheels only. pip install --only-binary :all: refuses sdists, so no setup.py runs during install. It would have refused tego-managed-agents-test, which shipped only an sdist. It does nothing against import-time or on-use code.
  • Install new dependencies somewhere disposable. Try a new package in a throwaway container with no ~/.aws, ~/.ssh or tokens mounted. In CI, keep deploy and publish secrets out of the job environment during dependency installation and pass them only to the step that needs them.
  • Scan before merge. Run osv-scanner scan -L requirements.txt on every pull request that changes dependencies; it catches a package once an advisory exists. Add guarddog pypi verify requirements.txt, whose heuristics such as cmd-overwrite and exec-base64 flag suspicious code before anyone files an advisory. Static rules read Python source, so a payload compiled into a native extension, as in sherpy, is harder for them to see.
  • Look at the package before adding it. The advisories list only one or two versions for each of these projects, all numbered 0.1 or 1.0. Check the release history, the maintainer's other projects, whether the linked repository exists and matches, and download counts.
  • Audit egress during installs. A pip install should only reach pypi.org and files.pythonhosted.org, or your internal mirror. In GitHub Actions, StepSecurity's Harden-Runner with egress-policy: audit logs every outbound connection per job, and any other destination during dependency install deserves a look.

If your team wants to know what a malicious dependency could reach in your pipelines, a red team code review tests exactly that, and our platform and cloud engineering team can set up hashed lockfiles, dependency scanning and secret-free install steps in CI. Open the chat and Yaali, our AI agent, will pass your question to an engineer.


Sources: OSV MAL-2026-17181 (reqparser), OSV MAL-2026-17183 (tego-managed-agents-test), OSV MAL-2026-17188 (sherpy), kam193 Bad packages: reqparser, kam193 Bad packages: tego-managed-agents-test, kam193 Bad packages: sherpy, compromised-packages-check pull request #140, compromised-packages-check pull request #136, Datadog Security Labs on GuardDog, GuardDog, setuptools bdist_wheel source, Python Packaging User Guide: package formats, pip secure installs, Python tutorial: modules, OSV-Scanner, OSV-Scanner usage, StepSecurity Harden-Runner.

Back to the blog, or read this post on the full site.