Skip to content

Restore Docker registry auth for credentials with a URL path - #313

Open
jurre wants to merge 1 commit into
mainfrom
jurre-investigate-issue-14717
Open

jurre wants to merge 1 commit into
mainfrom
jurre-investigate-issue-14717

Conversation

@jurre

@jurre jurre commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

What are you trying to accomplish?

Since #229, a Docker credential with a URL path only authenticates requests under /v2 plus that path. Registry URLs often include a web context path that registry API requests never use. A credential for https://artifactory.example.com/artifactory/docker-remote is scoped to /v2/artifactory/docker-remote, but clients request /v2/, /v2/token and /v2/docker-remote/.... Those requests go out without auth, so pulls fail.

This adds a host fallback. When no credential matches a /v2 request 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 /v2 request 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-remote to /v2/docker-remote, because /v2/ and /v2/token have 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.TryAuthCredential sets the token on any request it gets, so the host and port check in authenticateHostFallback is the only thing keeping an OIDC token on its own registry.
  • The fallback relies on Skip registering credentials for anonymous registries for egress allowlist #303 dropping anonymous registries when the handler is built. Without it, the fallback would pick an anonymous registry listed first for the host.
  • On a host with both Docker and Helm credentials, Helm OCI requests under /v2 now 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.json by 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. TestProxyDockerRegistryCredentialWithWebContextPath runs 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 the script/test command, with GOARCH=arm64 so -race can 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 credential or trying host fallback OIDC credential, and their pulls will succeed.

Checklist

  • I have run the complete test suite to ensure all tests and linters pass.
  • I have thoroughly tested my code changes to ensure they work as expected, including adding additional tests for new functionality.
  • I have written clear and descriptive commit messages.
  • I have provided a detailed description of the changes in the pull request, including the problem it addresses, how it fixes the problem, and any relevant details about the implementation.
  • I have ensured that the code is well-documented and easy to understand.

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>
@jurre
jurre marked this pull request as ready for review October 13, 2026 16:36
@jurre
jurre requested a review from a team as a code owner October 13, 2026 16:36
Copilot AI balanced review requested due to automatic review settings October 13, 2026 16:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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 /v2 requests.
  • 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants