Installing a Python package usually looks simple: run pip install, wait for dependency resolution, and start using the library. However, package installation isn't always passive. Python packaging tools may need to inspect package metadata, execute build backends, create wheels, and run installation-related code.

This becomes a security concern when the package being installed is untrusted or has been modified unexpectedly. A malicious package may attempt to execute Python code during installation, before the application itself ever imports the package.

pip 26.3 introduces an important security change for this situation. It blocks unexpected imports during installation, warns about unsafe imports afterward, and improves recovery from interrupted installations. The change aims to reduce the amount of third-party Python code that can unexpectedly execute during installation.

This does not mean pip can make every Python package safe. pip's own security documentation makes clear that installing untrusted wheels has never been considered completely safe because Python's import system is dynamic.

Why Import Execution During Installation Is a Security Problem

Python packages can contain much more than ordinary application modules. A distribution can include:

  • Python modules

  • Package metadata

  • Build configuration

  • Console scripts

  • Native extensions

  • Build dependencies

  • Installation-related behavior

A traditional installation workflow can therefore involve several stages where Python code may be loaded.

For example, consider a project with a package structure like this:

Code
myapp/
├── pyproject.toml
├── src/
│   └── myapp/
│       ├── __init__.py
│       └── cli.py
└── README.md

The __init__.py file may contain executable Python code:

Code
print("Package imported")

Normally, importing the package is expected to execute that code.

The security problem occurs when an installation process imports code that was not expected to be imported at that point.

If the package is compromised, that code could perform actions such as reading environment variables, accessing files, making network requests, or modifying the local environment.

The important distinction is that this risk exists before your application intentionally imports the package.

What Changed in pip 26.3

pip 26.3 includes a change specifically described as:

Code
Block unexpected imports during installation,
warn about unsafe imports afterward,
and improve recovery from interrupted installations.

This change is part of pip's 26.3 release and is associated with issue #13842.

The practical goal is to make installation behavior more predictable.

Instead of assuming that every import encountered during installation is acceptable, pip can distinguish expected installation activity from unexpected imports and take action when unsafe behavior is detected.

This is especially useful in automated environments where dependencies are installed during:

  • CI/CD builds

  • Docker image creation

  • application deployment

  • development environment setup

  • package build pipelines

  • automated dependency updates

Understanding Expected and Unexpected Imports

Not every import during installation is automatically malicious.

Python packaging itself relies on imports in several legitimate situations. Build systems can require Python modules to prepare metadata or build distributions.

For example, a project may define a build backend in pyproject.toml:

Code
[build-system]
requires = ["setuptools>=80"]
build-backend = "setuptools.build_meta"

The build process needs to load the configured backend.

That is different from an unrelated package unexpectedly importing application code or another module simply because it happens to be present in the environment.

The important security principle is therefore not:

Code
Block every import.

It is closer to:

Code
Allow installation-related imports that pip expects,
while detecting unexpected imports that could indicate unsafe behavior.

This distinction matters when troubleshooting a package installation failure after upgrading pip.

Check Your pip Version

Before testing the new behavior, verify the pip version being used by the environment.

Code
python -m pip --version

A typical result looks similar to:

Code
pip 26.3 from .../site-packages/pip (python 3.12)

Using:

Code
python -m pip

is preferable to relying on a globally available pip command because it makes it clearer which Python interpreter is executing pip.

You can also check:

Code
python -m pip show pip

If your project uses multiple Python installations, verify the interpreter and pip together:

Code
python --version
python -m pip --version

This avoids a common troubleshooting mistake where pip belongs to a different Python environment than the application.

Test Package Installation in an Isolated Environment

Do not test potentially unsafe packages directly inside a production environment.

Create a virtual environment first:

Code
python -m venv .venv

Activate it on Windows:

Code
.venv\Scripts\Activate.ps1

On Linux or macOS:

Code
source .venv/bin/activate

Then verify the environment:

Code
python --version
python -m pip --version

This provides a controlled location for testing package installation behavior.

For security testing, an isolated environment is still not equivalent to a sandbox. A virtual environment limits Python package changes, but it does not provide a complete security boundary against malicious native code or operating-system-level activity.

Use Installation Logs When Investigating Import Warnings

If pip reports an unexpected or unsafe import during installation, do not immediately bypass the warning.

First capture the installation output.

For example:

Code
python -m pip install example-package -v

For deeper diagnostics:

Code
python -m pip install example-package -vv

Verbose output can help identify which package, build step, or backend was involved.

You can also generate a log file:

Code
python -m pip install example-package --log pip-install.log

The useful troubleshooting question is:

Code
Which package caused the import, and why was that import required?

That is more useful than simply asking whether the installation succeeded.

Check the Package Before Installing It

pip's import protection should be treated as one layer of security rather than the complete solution.

Before installing a package in a production environment, check where it comes from.

For example:

Code
python -m pip index versions example-package

For internal packages, verify that the configured package index is the expected one.

You should also review the package version specified by your project:

Code
example-package==2.4.1

Pinning versions makes dependency changes easier to review.

For higher-risk applications, use hashes where appropriate:

Code
example-package==2.4.1 \
    --hash=sha256:<expected-hash>

Hash checking helps ensure that the downloaded artifact matches the artifact your dependency configuration expects. It does not prove that the package itself is trustworthy.

Test Installation in CI

CI pipelines are one of the places where unexpected installation behavior deserves particular attention.

A simple installation step might look like:

Code
steps:
  - name: Install dependencies
    run: |
      python -m pip install --upgrade pip
      python -m pip install -r requirements.txt

After moving to pip 26.3, monitor the installation logs for import-related warnings or failures.

For security-sensitive projects, avoid silently ignoring installation warnings.

A better pipeline pattern is:

Code
Resolve dependencies
        ↓
Verify dependency versions
        ↓
Install in isolated environment
        ↓
Review installation warnings
        ↓
Run tests
        ↓
Build deployment artifact

This makes dependency installation part of the software supply-chain process rather than treating it as an invisible setup step.

Common Mistakes

Assuming every pip warning means the package is malicious

An installation warning is a signal that deserves investigation. It is not automatically proof of malicious behavior.

First identify the package and installation stage involved.

Installing untrusted packages on the host system

Avoid testing unknown packages in an environment containing production credentials, SSH keys, cloud credentials, or sensitive source code.

Use a disposable environment with minimal permissions.

Assuming a virtual environment is a security sandbox

A virtual environment separates Python dependencies, but it does not isolate operating-system capabilities.

Do not treat:

Code
python -m venv test-env

as equivalent to a container or hardened sandbox.

Ignoring package build dependencies

A package can execute code through its build process as well as through its normal runtime modules.

Review pyproject.toml and the declared build backend when investigating unusual installation behavior.

Downgrading pip immediately

If an existing installation starts failing after a pip upgrade, first determine whether the failure is related to the new security behavior.

Blindly downgrading can remove security improvements without addressing the underlying package problem.

Best Practices for Production Projects

Practice

Why it matters

Use isolated environments

Limits dependency changes

Pin important dependencies

Makes dependency changes predictable

Review package sources

Reduces supply-chain risk

Monitor pip installation logs

Helps detect unexpected behavior

Keep pip updated

Receives security and compatibility fixes

Use dependency hashes where appropriate

Verifies downloaded artifacts

Minimize CI credentials

Limits impact if a package is compromised

Test dependency updates separately

Prevents unexpected changes from reaching production

The most important point is that pip's new protection should complement, not replace, dependency security practices.

Troubleshooting Checklist

If a package installation behaves differently after upgrading to pip 26.3, work through the following checks:

  1. Confirm the pip version.

Code
python -m pip --version
  1. Reproduce the issue inside a clean virtual environment.

Code
python -m venv test-env
  1. Install the package with verbose logging.

Code
python -m pip install package-name -vv
  1. Identify the package or build backend associated with the import warning.

  2. Check whether the package is coming from the expected package index.

  3. Review the project's pyproject.toml and build-system configuration.

  4. Check whether the package has a newer release that resolves the installation problem.

  5. Only consider a pip downgrade after understanding the compatibility or security trade-off.

Advantages and Disadvantages

Advantages

  • Reduces unexpected imports during package installation.

  • Makes unsafe installation behavior easier to identify.

  • Improves recovery from interrupted installations.

  • Adds another layer of protection to Python dependency installation.

  • Particularly useful for CI/CD and automated build environments.

Disadvantages

  • Some existing packages or unusual build workflows may expose compatibility issues.

  • Troubleshooting can require understanding Python packaging and build backends.

  • The feature does not make untrusted Python packages completely safe.

  • Virtual environments alone are still insufficient for executing highly untrusted code.

Summary

pip 26.3 makes package installation safer by blocking unexpected imports, warning about unsafe imports afterward, and improving recovery from interrupted installations. This is an important change for developers who install dependencies automatically through CI/CD, Docker builds, and deployment pipelines.

The right approach is not to treat the new behavior as a replacement for dependency security. Use isolated environments, review package sources, pin dependencies where appropriate, monitor installation logs, and investigate unexpected imports instead of immediately bypassing them.

For production Python projects, dependency installation should be treated as part of the software supply chain. The safer the installation process, the fewer opportunities there are for unexpected package behavior to reach your development or production environments.