The Malicious torchtriton Package That Hit PyTorch Users
On this page
The code was fine. The install wasn't — pip pulled an attacker's package with the right name off the public index.
| When | December 2022 |
|---|---|
| Target | PyTorch-nightly (Linux) users |
| Vendor | PyTorch / Meta; PyPI |
| Technique | Dependency confusion / name-squatting on PyPI |
| Impact | SSH keys, env vars, and system files exfiltrated via DNS |
- 1An attacker uploads a malicious torchtriton to public PyPI
- 2pip prefers PyPI over PyTorch's private index for that name (dependency confusion)
- 3PyTorch-nightly installs pull the trojan, which exfiltrates keys and files
What happened
Over the 2022 holidays, an attacker uploaded a malicious package named torchtriton to PyPI — the same name as a dependency PyTorch ships on its own nightly index. Because pip gives public PyPI precedence, anyone installing PyTorch-nightly on Linux via pip between Dec 25–30 pulled the malicious version, whose binary read SSH keys, git config, environment variables, and home-directory files and exfiltrated them via DNS to an attacker domain.
How the attack worked
Dependency confusion: when a private-index package name also exists on public PyPI, the installer may prefer the public one. The attacker registered PyTorch's private dependency name publicly and let pip do the rest.
Root cause
A build/install pipeline that trusted package names without pinning their source, so a public namespace collision became remote code execution on developers' machines.
What a control would have caught
Namespace reservation and index-source pinning (or hash-pinned lockfiles) prevent the public index from ever satisfying a private dependency — the exact gap here.
How to prevent it
- Pin the index and hashes for internal dependencies; reserve their names publicly.
- Treat install-time code as code — scan and sandbox it.
- Monitor for typo/name-squats of your packages.
Feel it yourselfThe replay lab plants a tampered dependency that runs attacker code at install — the supply-chain class.
FAQ
What is dependency confusion?
When a package name used on a private index also exists on public PyPI, the installer may pull the public one. Here the attacker registered the private dependency's name (torchtriton) on PyPI, and pip preferred it.
What did the malware do?
It read /etc/passwd, /etc/hosts, ~/.gitconfig, ~/.ssh/*, environment variables, and the first 1,000 files in the home directory, then exfiltrated them via DNS to an attacker domain.
How was it fixed?
PyTorch renamed the package to pytorch-triton, registered a dummy placeholder on PyPI to block re-squatting, and removed the malicious version with the PyPI security team.