Safeguard
Developer Tools•

Where should you set pip's index-url to enforce an internal mirror?

pip reads global, user and site config, then PIP_CONFIG_FILE, then env vars and flags. Where to set index-url, and what can override it in practice.

Safeguard Security Team
3 min read

Set index-url in pip's global configuration file for a baseline, repeat it in CI through a config file or environment variable, and accept that a developer can still override it with a command line flag. Pip applies options in a fixed order, so know which layer wins.

The layers

According to the pip documentation, there are three config file levels: global, user and site. They load in that order, then PIP_CONFIG_FILE if set, and later files override earlier values. Environment variables and command line options sit above all files.

Highest priority first:

  1. Command line options
  2. Environment variables, named PIP_ plus the option name in capitals with underscores
  3. Config files, where a command specific section such as [install] beats [global]

File locations

PlatformGlobalUser
Linux/etc/pip.conf (also under XDG_CONFIG_DIRS)$HOME/.config/pip/pip.conf
macOS/Library/Application Support/pip/pip.conf$HOME/Library/Application Support/pip/pip.conf
WindowsC:\ProgramData\pip\pip.ini%APPDATA%\pip\pip.ini

Site config sits in the virtual environment, as pip.conf or pip.ini, or at the Python installation root when no environment is active.

A minimal global file looks like this.

[global]
index-url = https://pypi.internal.example/simple

The key name matches the long option name without the leading dashes.

What can defeat your setting

  • A user running pip install --index-url ... overrides every file.
  • PIP_INDEX_URL in the environment overrides files.
  • PIP_CONFIG_FILE loads last and wins over other files. The docs also say that setting it to the null device disables all config loading, and that if a file exists at the path it names, the user config file is skipped.
  • A virtual environment with its own site file changes behaviour for that environment.

So a global file is a default, not a lock. Real enforcement comes from the network: block direct access to the public index from build hosts, so a developer who skips the setting gets an error rather than a quiet bypass.

Do not combine indexes carelessly

--extra-index-url adds more indexes, and pip does not rank them. It picks the best version match across all of them, so a public package can beat your private one. The pip docs call using it for packages not in the main repository unsafe because of dependency confusion. Point index-url at one internal index that proxies the public one, instead of adding extras.

Rollout steps

  1. Stand up the internal index and test it with a few projects.
  2. Push the global file through device management and bake it into CI images.
  3. Add PIP_INDEX_URL in CI as a second layer.
  4. Block the public index at the build network edge.
  5. Check the index access log for clients that still bypass it.

Try it yourself

Click through it at your own pace, or open it full screen.

Open the inventory and look at where each package came from. Source matters as much as version.

Safeguard's SBOM and dependency scanning can show where your dependencies come from, with a free scan at gold.safeguard.sh/scan.

Quick check

Does a global pip.conf stop a developer using another index?

No. Command line options and environment variables outrank config files, so back it with network controls.

Which wins, PIP_INDEX_URL or pip.conf?

The environment variable. The docs rank command line, then environment, then config files.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.