Agent Wranglers

SEC-103Recommended

Fetch private packages only from your own registry

Install packages with internal names only from your private registry. The public registry must never be able to answer for them.

How to do it

Skip this rule when you use no private packages. An attacker can publish a public package with your internal name and a higher version. Some package managers then install it, with all the build's secrets in reach. pip searches every index with no priority, so --extra-index-url next to a private index is unsafe. Give every internal npm package a scope, such as @example-shop/, and map that scope to the private registry. Register the same scope on the public registry too, so nobody else can claim it. For Python, set --index-url to one private mirror that proxies the public index and refuses your internal names from upstream. Install from the lock file as lock and audit dependencies says.

Examples

INI example

# .npmrc: the scope can only come from the private registry
@example-shop:registry=https://npm.internal.example.com/

INI example 2

# pip.conf: one index, a private mirror of the public one
[global]
index-url = https://pypi.internal.example.com/simple/

How to check

Search the build files, pip.conf, requirements*.txt and every .npmrc for extra-index-url. No match is found. Every internal npm package name starts with a scope. For each scope, npm config get @example-shop:registry prints the private registry, and the scope is owned by your organisation on the public registry.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/adversarial-testing/supply-chain-and-setup/dependency-confusion">Agent Wranglers security testing playbook</a>. In code you write, add a comment next to it with the same link.