Repository navigation
Conversation
Since #229, the Docker registry handler only uses an explicit credential for requests under the path in its url, prefixed with /v2. Registry URLs often include a web context path that never appears in registry API requests. A credential for https://artifactory.example.com/artifactory/docker-remote is scoped to /v2/artifactory/docker-remote, but clients request /v2/, /v2/docker-remote/... and /v2/token, so those requests go out without auth. When no OIDC, static, or automatic credential matches a /v2 request, fall back to the first explicit credential for the same host and port, trying OIDC first. This matches how url credentials worked before #229. Exact path matches still win, and the fallback only applies inside /v2, so other ecosystems on a shared host keep their own credentials elsewhere. Anonymous registries are dropped when the handler is built (#303), so the fallback never picks one. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
honeyankit
approved these changes
Oct 13, 2026
There was a problem hiding this comment.
🔵 Needs a closer look
The intentional expansion of credential scope is security-sensitive and warrants final human review.
0 open findings
What changed in this PR
Restores Docker authentication when registry credentials contain web context paths absent from /v2 API requests.
Changes:
- Adds same-origin OIDC/static host fallback for unmatched
/v2requests. - Preserves path-specific and automatic credential precedence.
- Adds unit and end-to-end coverage for token, Basic, OIDC, and Helm interactions.
| File | Description |
|---|---|
internal/handlers/docker_registry.go |
Implements host fallback authentication. |
internal/handlers/docker_registry_test.go |
Covers fallback precedence and boundaries. |
proxy_test.go |
Verifies complete registry challenge flows. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What are you trying to accomplish?
Since #229, a Docker credential with a URL path only authenticates requests under
/v2plus that path. Registry URLs often include a web context path that registry API requests never use. A credential forhttps://artifactory.example.com/artifactory/docker-remoteis scoped to/v2/artifactory/docker-remote, but clients request/v2/,/v2/tokenand/v2/docker-remote/.... Those requests go out without auth, so pulls fail.This adds a host fallback. When no credential matches a
/v2request by path, the handler uses the first explicit credential for the same host and port, OIDC before static, as it did before #229. Path matches and automatic credentials still take precedence.Anything you want to highlight for special attention from reviewers?
This partly undoes #229. A path-scoped credential now applies to any
/v2request on its host and port that nothing else matches, including other repositories and anonymous ones. If the credential can't read one of those, the registry can reject a pull that used to work anonymously. Keeping anonymous repositories unauthenticated would need a registry-specific map from URL paths to repositories, so I've left that as a follow-up.I chose the fallback over mapping URL paths onto registry paths, such as
/artifactory/docker-remoteto/v2/docker-remote, because/v2/and/v2/tokenhave no repository in the path and would need a host rule anyway. Ignoring the path altogether would also fix this, but the credential would then cover every path on the host instead of/v2, and override other ecosystems' credentials on a shared host.Worth a close look:
OIDCRegistry.TryAuthCredentialsets the token on any request it gets, so the host and port check inauthenticateHostFallbackis the only thing keeping an OIDC token on its own registry./v2now get the static Docker credential, as they already do when the Docker credential has no path.After merge, I'll check that the published image includes this commit, replay the reported failure against it, and bump the pin in dependabot-action's
docker/containers.jsonby hand. To roll back, revert that bump and this PR. Reverting only the pin isn't enough, because the weekly Dependabot update would bump it again.How will you know you've accomplished your goal?
The new tests fail on main and pass here.
TestProxyDockerRegistryCredentialWithWebContextPathruns pulls end to end through the proxy, against a fake registry that uses either a token or a Basic challenge.docker run --rm -e GOARCH=arm64 dependabot/proxy-builder-tests go test -race -shuffle=on -count=2 -v ./...: passed. This is thescript/testcommand, withGOARCH=arm64so-racecan use cgo on an arm64 host.golangci-lint run --new-from-rev=origin/main ./...: no issues.Once deployed, affected jobs will log
using host fallback static credentialortrying host fallback OIDC credential, and their pulls will succeed.Checklist