Registry client doesn't preserve effective URL after redirects - breaks tunnel/proxy scenarios
Description
The Stereoscope registry client fails to preserve the effective URL after HTTP redirects, causing issues when accessing registries through tunnels, proxies, or load balancers. Instead of using the effective URL from resp.Request.URL, it appears to reconstruct URLs from the original reference.Named authority.
Impact on Downstream Projects
This affects Syft and potentially other projects that depend on Stereoscope for OCI registry operations.
Problem Details
When a registry is accessed through a tunnel/proxy:
- Original reference:
tunnel.example.com/repo/image:tag
- Registry returns auth challenge referencing original domain:
original.registry.com
- Stereoscope reconstructs URLs using original domain instead of tunnel
- Subsequent requests fail because they bypass the tunnel
Expected Behavior
The registry client should:
- Preserve the effective URL from
resp.Request.URL after any redirects
- Use the effective host for all subsequent registry operations
- Only fall back to reference authority if no redirects occurred
Actual Behavior
Error shows original registry hostname instead of tunnel URL:
Get "https://jfrog.lumodev.com/api/docker/mult/v2/token?scope=repository%3Atest-docker%2Falpine%3Apull&service=docker&realm=https://jfrog.lumodev.com": dial tcp: lookup jfrog.lumodev.com: no host address
When the request should have been made to: ua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cx
Technical Details
The issue likely occurs in the registry client code where:
// PROBLEMATIC: Reconstructing from reference authority
url := fmt.Sprintf("https://%s/v2/%s/manifests/%s", ref.Registry(), ref.Repository(), ref.Tag())
// CORRECT: Preserve effective URL after redirects
effectiveURL := resp.Request.URL // Use this for subsequent requests
Suggested Fix Areas
-
HTTP Client Configuration:
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
// Preserve authorization headers and effective URL
return nil // Default behavior
},
}
-
URL Construction:
// After any auth/redirect flow, use effective URL
if effectiveHost := getEffectiveHost(lastResponse); effectiveHost != "" {
baseURL = fmt.Sprintf("https://%s", effectiveHost)
} else {
baseURL = fmt.Sprintf("https://%s", ref.Registry())
}
Environment
- Stereoscope version: v0.1.10
- Use case: JFrog Artifactory through zrok tunnel
- Client tools: Docker (works), Syft via Stereoscope (fails)
- OS: macOS
Reproduction Scenario
- Set up registry tunnel:
original.registry.com → tunnel.proxy.com
- Docker pull works:
docker pull tunnel.proxy.com/repo/image
- Stereoscope-based tools fail, reverting to
original.registry.com
Example Setup
- Original registry:
jfrog.lumodev.com
- Tunnel URL:
ua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cx
- Working:
docker pull ua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cx/test-docker/alpine:3.15
- Failing: Stereoscope-based tools trying to access
jfrog.lumodev.com directly
Related Standards
This aligns with OCI Distribution Spec and Docker Registry HTTP API v2, where clients should follow redirects and preserve effective URLs for subsequent requests.
Related Issues
- Related Syft issue: [will be filed separately]
Registry client doesn't preserve effective URL after redirects - breaks tunnel/proxy scenarios
Description
The Stereoscope registry client fails to preserve the effective URL after HTTP redirects, causing issues when accessing registries through tunnels, proxies, or load balancers. Instead of using the effective URL from
resp.Request.URL, it appears to reconstruct URLs from the originalreference.Namedauthority.Impact on Downstream Projects
This affects Syft and potentially other projects that depend on Stereoscope for OCI registry operations.
Problem Details
When a registry is accessed through a tunnel/proxy:
tunnel.example.com/repo/image:tagoriginal.registry.comExpected Behavior
The registry client should:
resp.Request.URLafter any redirectsActual Behavior
Error shows original registry hostname instead of tunnel URL:
When the request should have been made to:
ua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cxTechnical Details
The issue likely occurs in the registry client code where:
Suggested Fix Areas
HTTP Client Configuration:
URL Construction:
Environment
Reproduction Scenario
original.registry.com→tunnel.proxy.comdocker pull tunnel.proxy.com/repo/imageoriginal.registry.comExample Setup
jfrog.lumodev.comua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cxdocker pull ua25m32e2lnmahwbxbo0uw7icem1vhj9.zrok.cx/test-docker/alpine:3.15jfrog.lumodev.comdirectlyRelated Standards
This aligns with OCI Distribution Spec and Docker Registry HTTP API v2, where clients should follow redirects and preserve effective URLs for subsequent requests.
Related Issues