# Public registry shadowing of internal package names

Internal package, gem, plugin or dependency names that resolve from a public registry or extra index

_Area: Software supply chain and CI/CD. Seen in 6 disclosed reports; 4 confirmed bounties, median $1,500, range $200-$5,000; latest 2023-05-06. Updated 2026-10-23._

## How it works

A build or install trusts a name, not a source. When an internal-only package name is not reserved on the public registry, anyone can publish that name. The resolver then picks the public copy — because the name matches, because the public index is preferred, or because a tool converts a private reference into a public one. The attacker's package runs install-time code in the build or developer environment. The broken assumption: "this name only exists internally."

## Where it shows up

- `pip install` with `--extra-index-url` (public PyPI wins over the private index) [E3](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-google-remote-code-execution.md)[E6](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-malicious-pytorch-dependency-torchtriton-on-pypi-everything-you-need-to-know.md)
- Internal names visible in requirements.txt, lockfiles, `pip freeze`, front-end bundles, or error output [E2](https://bugbountylibrary.com/r/h1%3A946409.md)[E3](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-google-remote-code-execution.md)
- Unscoped gems or packages with no source pin; manual `gem install`/`npm install`/`pip install` [E5](https://bugbountylibrary.com/r/h1%3A1104874.md)
- WordPress plugin slugs under `/wp-content/plugins/<slug>/` absent from the public SVN [E4](https://bugbountylibrary.com/r/h1%3A1364851.md)
- Tools that rewrite private Git dependencies into registry packages [E1](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion.md)

## How to review

The invariant: every internal dependency name must be either reserved on the public registry or pinned to a single private source, and no resolver path may fall back to a public index for it.

- Enumerate internal names from manifests, lockfiles and bundles; check each against the public registry.
- Confirm index configuration: no `extra-index-url` mixing; use a single private index or explicit source pins.
- Check that trust decisions read metadata from a trusted source, not from the artifact being installed [E1](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion.md).
- Confirm CI and developer machines share the same pinning; manual installs bypass CI hardening [E5](https://bugbountylibrary.com/r/h1%3A1104874.md).

## Variants seen

- Unclaimed internal name squatted on public PyPI, installed by a build server [E2](https://bugbountylibrary.com/r/h1%3A946409.md)
- `extra-index-url` precedence pulling a public package over the private one [E3](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-google-remote-code-execution.md)[E6](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-malicious-pytorch-dependency-torchtriton-on-pypi-everything-you-need-to-know.md)
- Unscoped internal gem claimed on Rubygems.org [E5](https://bugbountylibrary.com/r/h1%3A1104874.md)
- Internal WordPress plugin slug claimed in the public directory, delivered via auto-update [E4](https://bugbountylibrary.com/r/h1%3A1364851.md)
- Tool converting private Git deps to public registry packages, validated against attacker-controlled metadata [E1](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion.md)

## Impact and severity

RCE on build servers and developer hosts, private repo access, and credential/SSH-key exfiltration via DNS tunneling [E1](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion.md)[E2](https://bugbountylibrary.com/r/h1%3A946409.md)[E3](https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-google-remote-code-execution.md)[E6](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-malicious-pytorch-dependency-torchtriton-on-pypi-everything-you-need-to-know.md). Severity is high because install-time code runs with build credentials. Worse when names leak widely, when public index precedence is default, and when manual installs bypass hardened CI [E5](https://bugbountylibrary.com/r/h1%3A1104874.md).

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion.md
- E2: https://bugbountylibrary.com/r/h1%3A946409.md
- E3: https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-google-remote-code-execution.md
- E4: https://bugbountylibrary.com/r/h1%3A1364851.md
- E5: https://bugbountylibrary.com/r/h1%3A1104874.md
- E6: https://bugbountylibrary.com/r/blog%3Awiz-io-blog-malicious-pytorch-dependency-torchtriton-on-pypi-everything-you-need-to-know.md
