Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

401 When trying to download assests from private repo



  • ProGet Version: 2025.x (latest Docker image as of January 2026)

    Feed Types Affected: npm, PyPI

    Issue Description:

    ProGet connector forwards credentials for package metadata requests but does NOT forward credentials for file download requests, causing downloads to fail with HTTP 500 errors.

    Pattern:

    • ✅ Metadata requests: HTTP 200 (credentials forwarded successfully)
    • ❌ File downloads: HTTP 500 "WebException" (credentials NOT forwarded, underlying 401 from upstream)

    Test Case (npm):

    Setup:

    Command:
    npm install debug --registry http://localhost/npm/feed-name/

    Results:
    ✅ Metadata: GET /javascript/debug → HTTP 200 (success)
    ❌ Tarball: GET /javascript/files/.../debug-4.4.3.tgz → HTTP 500 (failure)

    npm error: 500 Internal Server Error - WebException

    Root Cause:

    The upstream registry (Chainguard) uses content-addressable storage where files are at different paths than metadata:

    ProGet forwards credentials to the base URL but not to the /files/ sub-path.

    Related Bugs:

    This appears similar to Bug PG-1121 (fixed in 4.8.6), but the issue persists in ProGet 2025.x for npm and PyPI feeds.

    Questions:

    1. Was PG-1121 fix applied to npm/PyPI feeds, or only NuGet?
    2. Is there a configuration option to forward credentials to all paths under the connector base URL?
    3. Is this a known limitation with content-addressable storage URLs?


  • Wanted to share the output from a client trying to install a package:

    25 silly packumentCache corgi:http://localhost/npm/Chainguard/lodash cache-miss
    26 http fetch GET 200 http://localhost/npm/Chainguard/lodash 765ms (cache miss)
    27 silly packumentCache corgi:http://localhost/npm/Chainguard/lodash set size:6616 disposed:false
    28 http fetch GET http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz attempt 1 failed with 500
    29 http fetch GET http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz attempt 2 failed with 500
    30 http fetch GET http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz attempt 3 failed with 500
    31 http fetch GET 500 http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz 73187ms attempt #3 (cache skip)
    32 verbose stack HttpErrorGeneral: 500 Internal Server Error - GET http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz - WebException
    32 verbose stack     at C:\Program Files\nodejs\node_modules\npm\node_modules\npm-registry-fetch\lib\check-response.js:103:15
    32 verbose stack     at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
    33 verbose statusCode 500
    34 verbose pkgid lodash@http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz
    35 error code E500
    36 error 500 Internal Server Error - GET http://localhost/npm/Chainguard/lodash/-/lodash-4.17.20.tgz - WebException
    37 silly unfinished npm timer reify 1768329298512
    38 silly unfinished npm timer reify:unpack 1768329299498
    39 silly unfinished npm timer reifyNode:node_modules/lodash 1768329299498
    

    We have this same behavior for both NPM and Python. This presents as a 401 in the WebUI but a 500 from a client.


  • inedo-engineer

    Hi @spencer-seebald_1146 ,

    Thanks for putting all the details together, this is really helpful! In theory, what you're doing should work... and I don't know why it's not. But it sounds like it'd be "trivial" to reproduce in a debug environment, so let's start there :)

    All we really need are credentials. It looks like your end-user opened a ticket on this issue as well (EDO-12512), so I will just add your email to that ticket and respond there with the same request.

    Once we have credentials, we'll try reproducing/fixing and hopefully get this working in no time :)

    Cheers,
    Alana


  • inedo-engineer

    Hi @spencer-seebald_1146 ,

    I was able to identify the issue.

    When you visit the URL in ProGet, then ProGet will visit this URL (slightly trimmed) with the appropriate authorization header:

    https://libraries.cgr.dev/javascript/..../lodash/-/lodash-4.17.20.tgz
    

    However, that URL will issue a 307 redirect to the following:

    /artifacts-downloads/javascript/namespaces/15f7d141c3b76b85/repositories/.../downloads/ABmYrfCH......KpxO1ducu3xmMRtw==
    

    ProGet then follows the redirect, but does not send the authorization header. And thus, a 401 is issued. This is actually the default/expected behavior in HttpClient (i.e. the library in .NET we use) and most clients in other languages (Java, Go, Ruby, etc.) as well.

    Of course it can be worked-around by disabling auto-redirect and implementing yourself to follow the URl with the same header. But that's not so common and, as such, it's not a common practice for servers to issue redirects that require authentication; we see other services handle the redirect using some kind of token in the querystring.

    On our end, this has not been an issue to date. This is logic is buried pretty deep and it's not an easy fix without changing code everything relies on. I'm kind of surprised npm and pip override the default behavior in the fetch() and requests libraries.

    Anyway, it sounds like you can make a change on the private repository server code... so I would here would be to just disable authentication on your artifacts-downloads endpoint. I mean that URL is basically authenticated anyway.... it's so long (I stripped like 1000 characters) that it's basically a password.

    Thanks,
    Alana


Log in to reply
 

Inedo Website HomeSupport HomeCode of ConductForums GuideDocumentation