Repository navigation
Description
Description
Requests to a private wheel cache return HTTP 401 despite valid Basic authentication credentials in netrc.
The regression was introduced by commit cae6a49fca4dcdcf53f5fd308753ee408aac2db1 — feat(auth): add URL-dispatched session auth for GitHub and GitLab.
Confirmed in a builder container running Fromager 0.101.0.
Observed behavior
During a wheel build:
WARNING banks-2.5.0: network error checking wheel cache for 2.5.0
at https://packages.redhat.com/lightwell/python/validated/simple/:
401 Client Error: Unauthorized for url:
https://packages.redhat.com/lightwell/python/validated/simple/banks/
The builder generates a netrc file and passes its path through NETRC. The same credentials successfully authenticate using a standard Requests session.
Minimal reproduction
Provide valid credentials for a private index through either ~/.netrc or a file referenced by NETRC:
machine packages.redhat.com login YOUR_USERNAME password YOUR_PASSWORD
Set file permissions to 0600, then run this in an environment with Fromager installed:
NETRC=/path/to/private.netrc python - <<'PYTHON'
import requests
from fromager.request_session import session
url = (
"https://packages.redhat.com/"
"lightwell/python/validated/simple/banks/"
)
for name, client in [
("requests", requests.Session()),
("fromager", session),
]:
response = client.get(url, timeout=30, allow_redirects=False)
print(
name,
response.status_code,
"auth sent:",
"Authorization" in response.request.headers,
)
response.close()
PYTHONObserved output:
requests 200 auth sent: True
fromager 401 auth sent: False
This requires access to the private index; another index requiring netrc Basic authentication can be substituted.
Cause
The commit installs a custom authentication handler:
s.auth = authRequests performs its automatic netrc lookup only when neither request-specific nor session authentication is configured:
if self.trust_env and not auth and not self.auth:
auth = get_netrc_auth(url)Setting session.auth therefore suppresses automatic netrc lookup. SessionAuth handles registered GitHub/GitLab hosts, but supplies no authentication for unregistered hosts such as the private wheel server.
Verification
Using the same builder image, input package, and credentials:
| Authentication implementation | Result |
|---|---|
| Original Fromager 0.101.0 | HTTP 401; no Authorization header |
Only request_session.py restored from before cae6a49 |
HTTP 200; wheel CLI passes cache lookup |
| Proposed netrc fallback | HTTP 200; wheel CLI passes cache lookup |
Both home-directory and explicit NETRC locations reproduce the regression in request-preparation tests. Restoring the earlier module succeeds while retaining the builder’s temporary netrc location.
Expected behavior and proposed fix
For hosts without a registered authentication callback, use matching netrc credentials as HTTP Basic authentication.
A proposed fix is available in PR #1461, with regression coverage for both netrc locations, host matching, GitHub/GitLab authentication, and explicit credentials.
Activity
tiran commentedon Nov 9, 2026
Summary
In #1173 I changed requests' session auth to no longer parse netrc by default. Instead trusted hosts must register a callback that returns auth headers.
Options
netrcparsing for their hostsDEFAULTcallback feature that is called when no host-specific callback is registered. Register a default callback that restoresnetrcparsing for all hosts. This allows users to control and override callback behavior.SessionAuth.get()to always fall back toget_netrc_auth