feat(registry): list private-registry tags in autocomplete - #60
Merged
Conversation
Image-tag suggestions (editor `image:` lines and the create-container form) now also list tags from a configured private registry via the Docker Registry HTTP API v2 — previously only Docker Hub tags were offered. - ImageTags branches on the ref's host: docker.io keeps using Hub's public API; any other host is served by a new v2 client that performs the Bearer-token handshake (or Basic auth) using the registry's stored, encrypted credentials. - Only hosts the admin configured under Registries are ever contacted; an unconfigured host yields no remote tags (no request is made). Security (this is the SSRF-sensitive part): - A guarded dialer enforces, at connect time on the resolved IP, that every outbound request and redirect goes either to the configured registry host or to a non-internal address — closing IPv6, IPv4-mapped, decimal/hex/octal and DNS-rebinding vectors. It dials the verified IPs directly (no second resolution → no TOCTOU). - Token realms must be https for non-local registries (no cleartext credential leak); cleartext Basic is confined to loopback registries. - The repo path is validated before it reaches the URL; responses are size- and time-bounded; redirects are capped and can't downgrade https. Tests cover the bearer handshake, direct Basic auth, repo-path parsing, and pentests: insecure/internal realms (incl. IPv6 / v4-mapped / unspecified) are rejected, the guarded dialer blocks internal non-registry targets, an unconfigured host makes no request, and an unsatisfiable Basic challenge yields no tags.
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.
Summary
Image-tag suggestions (editor
image:lines and the create-container form) now also list tags from a configured private registry via the Docker Registry HTTP API v2 — previously only Docker Hub tags were offered. The frontend already sent the full repo (incl. host), so this is almost entirely backend.ImageTagsbranches on the ref's host:docker.iokeeps using Hub's public API; any other host is served by a new v2 client that performs the Bearer-token handshake (or Basic auth) using the registry's stored, encrypted credentials.AuthForHost); an unconfigured host yields no remote tags and makes no request.Security — the SSRF-sensitive part (HIGH finding found in review, fixed, re-verified)
The token realm and redirect targets come from the registry's responses (attacker-influenced if a registry is compromised). Controls:
[::1],[fd00::1]), IPv4-mapped ([::ffff:169.254.169.254]), decimal/hex/octal IPv4 encodings, and DNS-rebinding — vectors a naive literal check misses. It dials the verified IPs directly (no re-resolution → no TOCTOU), and fails closed if any resolved IP is internal.Type of change
Checklist
go test -short ./...andgo vet ./...passgofmtgate is cleanweb/distdocs/andCHANGELOG.mdNotes for reviewers
Pentests in
internal/docker/registry_tags_test.go: insecure/internal realms (incl. IPv6 / v4-mapped / unspecified) rejected,TestGuardedDialer_BlocksInternalNonRegistry, unconfigured-host-makes-no-request, and unsatisfiable-Basic-challenge → no tags; plus the happy-path bearer handshake and direct Basic auth against an httptest registry. The HIGH SSRF gap from the first review pass (IPv6/numeric realm bypass) was fixed with the guarded dialer and independently re-verified.