Is there an existing issue for this?
Package ecosystem
uv, using GitHub-hosted Dependabot in a private repository.
Package manager version
uv 0.12.18 (x86_64-unknown-linux-gnu), as reported in the affected Dependabot job.
Language version
Python 3.11.15, as reported by Dependabot in the affected job.
Manifest location and content before the Dependabot update
The repository contains /pyproject.toml and /uv.lock.
Relevant pyproject.toml excerpt, with the private project name anonymized:
[project]
name = "private-application"
This is the application’s own project name, not a third-party dependency being updated. It is not published on public PyPI.
Dependency packages and lockfile artifacts use our private AWS CodeArtifact index.
dependabot.yml content
Relevant configuration from the affected setup, with private registry identifiers anonymized:
version: 2
registries:
private-python:
type: python-index
url: https://example.d.codeartifact.amazonaws.com/pypi/
username: aws
password: $PASSWORD
replaces-base: true
updates:
- package-ecosystem: "uv"
directory: "/"
registries:
- private-python
schedule:
interval: "daily"
No versioning-strategy override was active in the affected run. The job definition recorded "requirements-update-strategy": null.
Updated dependency
The affected run attempted multiple dependency updates.
The unexpected request uses the application’s project name rather than either dependency name. This report concerns that disclosure, independently of dependency-resolution errors in the same run.
What you expected to see, versus what you actually saw
Expected
With the configured Python index marked replaces-base: true, Dependabot should respect the replacement registry when classifying the project and avoid sending its private project name to public PyPI.
Actual
Dependabot requests:
https://pypi.org/pypi/<-- private-project-name-- >/json/
The request redirects to the endpoint without a trailing slash and returns HTTP 404. The project name has already been sent to public PyPI regardless of the response.
Source evidence
In Python UpdateChecker at commit 89a9e44, check_pypi_for_library_match directly calls:
response = Dependabot::RegistryClient.get(
url: "https://pypi.org/pypi/#{normalised_name(name)}/json/"
)
This method does not check whether configured Python registry credentials have replaces-base: true.
The uv UpdateChecker inherits the Python UpdateChecker.
Could library detection respect replaces-base: true, skip the public lookup, and use an appropriate local-metadata fallback? Regression coverage should verify that this configuration makes no public PyPI request containing the project name.
Native package manager behavior
We have not independently verified native uv behavior using request-level tracing.
The evidence here comes from the hosted Dependabot job and the separate HTTP request implemented in Dependabot’s Ruby update checker.
Images of the diff or a link to the PR, issue, or logs
Sanitized excerpts from the Dependabot run on October 8, 2026.
Relevant job-definition fields; other fields omitted:
{
"credentials-metadata": [
{
"type": "python_index",
"index-url": "https://example.d.codeartifact.amazonaws.com/pypi/",
"replaces-base": true
}
],
"package-manager": "uv",
"requirements-update-strategy": null,
"repo-private": true
}
HTTP log excerpt, with the project name redacted:
proxy | 2026/10/08 06:25:46 [018] GET https://pypi.org:443/pypi/<-- private-project-name-- >/json/
proxy | 2026/10/08 06:25:46 [018] 301 https://pypi.org:443/pypi/<-- private-project-name-- >/json/
proxy | 2026/10/08 06:25:46 [020] GET https://pypi.org:443/pypi/<-- private-project-name-- >/json
proxy | 2026/10/08 06:25:46 [020] 404 https://pypi.org:443/pypi/<-- private-project-name-- >/json
Later occurrences in the same run are marked as cached by the proxy. Caching does not prevent the initial disclosure.
Smallest manifest that reproduces the issue
The following is a proposed minimal reproduction based on the observed code path; it has not yet been independently tested:
[project]
name = "private-application"
version = "0.1.0"
description = "Private application"
requires-python = ">=3.11"
dependencies = [
"requests>=2.31,<3",
]
[[tool.uv.index]]
name = "private-python"
url = "https://example.d.codeartifact.amazonaws.com/pypi/"
default = true
Reproduction steps:
Use a private repository with a project name that is absent from public PyPI.
Generate and commit uv.lock through a working private index, with a dependency version that has an available update.
Configure Dependabot as shown above, including replaces-base: true and no explicit versioning-strategy.
Trigger a Dependabot version-update check.
Inspect the proxy logs for /pypi/<-- private-project-name-- >/json/ requests to public PyPI.
Is there an existing issue for this?
Package ecosystem
uv, using GitHub-hosted Dependabot in a private repository.
Package manager version
uv 0.12.18 (x86_64-unknown-linux-gnu), as reported in the affected Dependabot job.
Language version
Python 3.11.15, as reported by Dependabot in the affected job.
Manifest location and content before the Dependabot update
The repository contains /pyproject.toml and /uv.lock.
Relevant pyproject.toml excerpt, with the private project name anonymized:
[project]
name = "private-application"
This is the application’s own project name, not a third-party dependency being updated. It is not published on public PyPI.
Dependency packages and lockfile artifacts use our private AWS CodeArtifact index.
dependabot.yml content
Relevant configuration from the affected setup, with private registry identifiers anonymized:
No versioning-strategy override was active in the affected run. The job definition recorded "requirements-update-strategy": null.
Updated dependency
The affected run attempted multiple dependency updates.
The unexpected request uses the application’s project name rather than either dependency name. This report concerns that disclosure, independently of dependency-resolution errors in the same run.
What you expected to see, versus what you actually saw
Expected
With the configured Python index marked replaces-base: true, Dependabot should respect the replacement registry when classifying the project and avoid sending its private project name to public PyPI.
Actual
Dependabot requests:
https://pypi.org/pypi/<-- private-project-name-- >/json/
The request redirects to the endpoint without a trailing slash and returns HTTP 404. The project name has already been sent to public PyPI regardless of the response.
Source evidence
In Python UpdateChecker at commit 89a9e44, check_pypi_for_library_match directly calls:
response = Dependabot::RegistryClient.get(
url: "https://pypi.org/pypi/#{normalised_name(name)}/json/"
)
This method does not check whether configured Python registry credentials have replaces-base: true.
The uv UpdateChecker inherits the Python UpdateChecker.
Could library detection respect replaces-base: true, skip the public lookup, and use an appropriate local-metadata fallback? Regression coverage should verify that this configuration makes no public PyPI request containing the project name.
Native package manager behavior
We have not independently verified native uv behavior using request-level tracing.
The evidence here comes from the hosted Dependabot job and the separate HTTP request implemented in Dependabot’s Ruby update checker.
Images of the diff or a link to the PR, issue, or logs
Sanitized excerpts from the Dependabot run on October 8, 2026.
Relevant job-definition fields; other fields omitted:
{ "credentials-metadata": [ { "type": "python_index", "index-url": "https://example.d.codeartifact.amazonaws.com/pypi/", "replaces-base": true } ], "package-manager": "uv", "requirements-update-strategy": null, "repo-private": true }HTTP log excerpt, with the project name redacted:
Later occurrences in the same run are marked as cached by the proxy. Caching does not prevent the initial disclosure.
Smallest manifest that reproduces the issue
The following is a proposed minimal reproduction based on the observed code path; it has not yet been independently tested:
Reproduction steps:
Use a private repository with a project name that is absent from public PyPI.
Generate and commit uv.lock through a working private index, with a dependency version that has an available update.
Configure Dependabot as shown above, including replaces-base: true and no explicit versioning-strategy.
Trigger a Dependabot version-update check.
Inspect the proxy logs for /pypi/<-- private-project-name-- >/json/ requests to public PyPI.