Typosquatting means publishing a package whose name resembles a popular one so that a mistyped install pulls in malicious code. In Python the risk comes from two things: names that differ by one character, and projects that pull from more than one index. Pin exact names, use hashes and review any package you cannot place.
How do Python package names work?
The Python Packaging specification on name normalization says names are case insensitive and that runs of period, underscore and hyphen are treated as the same. Its example lists friendly-bard, Friendly-Bard, FRIENDLY-BARD, friendly.bard and friendly_bard as all equivalent.
This has one useful consequence. An attacker cannot register a separator variant of an existing name, because the normalized forms collide. But a different spelling is a different name. A package named requets next to requests, or a name with an extra letter, normalizes to something else and is free to register.
What is typosquatting in the ATT&CK model?
MITRE's technique T1195.001, Compromise Software Dependencies and Development Tools, says adversaries may use typosquatting or name confusion by choosing names similar to popular libraries to deceive a user. The same page notes that popular packages can be targeted to reach their users, that abandoned packages may be re-registered, and that CI/CD components such as GitHub Actions can be targeted too.
Constructed example: a developer writes a setup script at midnight and types the name of an HTTP library with one letter swapped. The install succeeds, because the swapped name exists. The package imports the real library so everything works, and also runs code at install time to read environment variables. Nothing breaks, so nothing is noticed.
What is dependency confusion and how is it different?
Typosquatting depends on a human typo. Dependency confusion needs no mistake from the user. PEP 708 describes the situation: a user expects package A from repository X, but someone publishes package B under the same name to repository Y, and pip, configured with several indexes, picks it. The PEP gives the PyTorch case of the internal package torchtriton, which was meant to come from the project's own index but whose name was not claimed on PyPI.
PEP 708 proposed a mechanism to stop this and, according to its page, was rejected after three years in a provisional state because the conditions for acceptance were not met. So do not assume the Python tooling prevents this for you. Configuration is your defense.
How to check or apply this
- Install from a lock file, not from names typed by hand. Review changes to it like code.
- Use pip's hash-checking mode for deployments, so an unexpected file fails to install. pip documents it under secure installs.
- Use one index where you can. If you need a private index, make it the only one, or proxy public packages through it, and reserve your internal names on the public index.
- Before adding a new dependency, check the project's name, age, release history, linked repository and maintainers. A package with a popular name and a single release last week deserves suspicion.
- Disable or review install time scripts where your tooling allows.
- Monitor new dependency additions in pull requests, and scan for known malicious packages automatically.
- Rotate any secret that was present on a machine or runner that installed something unexpected.
What can tooling do?
Safeguard scans dependencies and builds software bills of materials, and its policies and gates can block a pull request that adds a package you have not approved. The free scan at gold.safeguard.sh/scan covers up to 100 dependencies in your browser. These checks help you notice a surprising name. They do not replace reading the diff.
What should a review look at?
A two minute check catches many cases. Compare the name letter by letter with the project you meant. Open the project page and see whether the repository link points to the real source and whether that repository links back. Look at the release history: a long history with steady releases is a good sign, while a brand new project with one release and a popular sounding name is a warning. Check who maintains it, and search the issue tracker of the real project for mentions of lookalikes.
Quick check
Can someone register the same package name with underscores instead of hyphens?
No. Python normalizes case and treats runs of period, underscore and hyphen as the same, so those variants resolve to one name.
What is the difference between typosquatting and dependency confusion?
Typosquatting relies on a mistyped name. Dependency confusion relies on an installer choosing a public package over an internal one with the same name, because of how indexes are configured.
Sources
- Python Packaging, Names and normalization
- MITRE ATT&CK T1195.001, Compromise Software Dependencies and Development Tools
- PEP 708, Extending the Repository API to Mitigate Dependency Confusion Attacks
- pip documentation, Secure installs
Last reviewed: 18 October 2026.