Skip to content

fix(login): accept equivalent registry hosts in auth creds callback - #5128

Open
xianyuwu wants to merge 1 commit into
containerd:mainfrom
xianyuwu:fix/login-host-port-mismatch
Open

fix(login): accept equivalent registry hosts in auth creds callback#5128
xianyuwu wants to merge 1 commit into
containerd:mainfrom
xianyuwu:fix/login-host-port-mismatch

Conversation

@xianyuwu

@xianyuwu xianyuwu commented Aug 7, 2026

Copy link
Copy Markdown

PR Title

fix(login): accept equivalent registry hosts in auth creds callback

PR Body

Summary

nerdctl login fails against registries served on the default HTTPS port (443)
with:

FATA failed to call rh.Authorizer.AddResponses: expected acArg to be "harbor.example.io:443", got "harbor.example.io"

docker login works fine against the same registry.

Fixes #3992
Refs #3245

Root cause

In pkg/cmd/login/login.go, the credentials callback passed to the containerd
authorizer used a strict string equality check:

authCreds := func(acArg string) (string, string, error) {
    if acArg == host { ... }
    return "", "", fmt.Errorf("expected acArg to be %q, got %q", host, acArg)
}

However, the two sides of the comparison are built differently:

  • host comes from dockerconfigresolver.Parse(), which appends the
    standard HTTPS port explicitly
    when the user did not specify one
    (registryurl.go), so host is harbor.example.io:443.
  • acArg is passed by containerd's dockerAuthorizer.AddResponses() as
    last.Request.URL.Host, i.e. the host of the actual request, which is
    harbor.example.io — without the default port.

The same fragility produces #3245: logging in to docker.io resolves to
index.docker.io:443, while the actual registry endpoint calling back is
registry-1.docker.io.

Fix

Replace the strict equality check with an equivalence check
(isEquivalentRegistryHost) that additionally accepts:

  1. The same hostname with the default HTTPS port (443) omitted — when the user
    did not explicitly configure a non-default port.
  2. Docker Hub aliases: index.docker.io (the address docker.io resolves to)
    and registry-1.docker.io (the actual registry endpoint).

Callback hosts carrying an explicit non-standard port still must match
exactly, so credentials are never served to a different endpoint.

This mirrors the equivalence rules already encoded in
RegistryURL.AllIdentifiers() for credential lookup.

Test plan

Added pkg/cmd/login/login_test.go with table-driven cases covering:

$ go test -v -run TestLoginAuthCredsAcceptsEquivalentHosts ./pkg/cmd/login/...
--- PASS: TestLoginAuthCredsAcceptsEquivalentHosts (0.00s)
    --- PASS: .../exact_host_with_standard_port
    --- PASS: .../host_without_default_port
    --- PASS: .../docker.io_alias_without_port
    --- PASS: .../docker.io_alias_with_port
    --- PASS: .../mismatched_host
    --- PASS: .../explicit_non-standard_port_not_dropped
    --- PASS: .../different_explicit_port
PASS
ok      github.com/containerd/nerdctl/v2/pkg/cmd/login

The failing scenarios from both issues were reproduced against a private Harbor
registry served on port 443 (nerdctl login --insecure-registry); the unit
test cases above encode exactly those mismatches.

Parse() appends the standard HTTPS port to the registry address, but the
containerd authorizer calls the credentials callback with the request URL
host, which omits the default port (or uses the registry-1.docker.io alias
for Docker Hub). The strict equality check then fails and login aborts.

Replace the strict equality check with an equivalence check that accepts
the same hostname with the default port omitted, and the Docker Hub
index.docker.io/registry-1.docker.io alias pair. Callback hosts with an
explicit non-standard port must still match exactly.

Fixes containerd#3992
Refs containerd#3245

Signed-off-by: rainwu <xianyuwu@foxmail.com>
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.

Unable to log in to private registry

1 participant