Docker Hub credentials are now read first from the session of the account signed in to Docker Desktop, through the Docker Desktop secrets engine (github.com/docker/secrets-engine/client), and from the Docker CLI config file and its credential helpers otherwise. Other registries keep using the config file only.
The OAuth access token is passed as the password of the signed-in account, never as an IdentityToken, which containerd sends as a refresh token. It flows unchanged to the engine in X-Registry-Auth and through the OCI resolver as an OAuth password grant.
Compose falls back to the config file when Desktop is not running, nobody is signed in, the session is expired or about to expire, or the lookup fails (the last logged as a warning). The session is shared process wide, cached until shortly before it expires, and an unusable session is not asked for again. Lookups are bounded by a 5s timeout, as the SDK applies none by default.
Used by pull, push, publish, config --resolve-image-digests, oci:// remote resources and dry-run. The classic builder and use_api_socket keep config file credentials, as a short-lived token copied into a container would go stale.
Signed-off-by: Alano Terblanche <[email protected]>
compose-go's loader now silently renames both deprecated
x-initialSync and x-develop extensions to their official
initial_sync and develop attributes before compose ever sees them
as extensions, so the legacy lookups and deprecation warnings for
both can no longer be reached. That's why the e2e test asserting on
the x-initialSync warning broke under the bump.
Simplify both lookups to rely on the promoted fields directly, and
rewrite the e2e test to check the legacy attribute still triggers a
real initial sync instead of asserting on an unreachable message.
Signed-off-by: Guillaume Lours <[email protected]>
compose-spec/compose-go#931 is merged: TestBuildAdditionalContextDisabledService,
red until now by design, passes for real against the released compose-go pin.
Signed-off-by: Nicolas De Loof <[email protected]>
compose-spec/compose-go#866 is merged: jobs top-level element, container
specification layered as ContainerSpec/WorkloadSpec, pre_start hooks
carrying the full container specification resolved at load time. Bump
to the merged head and adapt in the same movement — composite literals
setting moved fields wrap them into the embedded ContainerSpec /
WorkloadSpec (promoted field access was already source-compatible, so
this is literal-only, no behavior change), and pre_start handling is
typed against PreStartHook.
Co-Authored-By: Claude Fable 5 <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
The github.com/AlecAivazis/survey/v2 module was archived and is no longer
maintained. Looking at the code, we didn't really use most of its features;
survey mostly provided terminal input handling around a simple yes/no
question.
Replace the interactive confirmation implementation with a small local
prompt reader while keeping the exported prompt types and existing
non-terminal prompt behavior unchanged. Preserve the confirmation hint,
default handling, retries for invalid input, and Ctrl+C handling.
Interactive prompts continue to use raw terminal input so Ctrl+C is handled
by the prompt instead of requiring a second interrupt to terminate the
process.
Signed-off-by: Sebastiaan van Stijn <[email protected]>
The TTY renderer accumulated display-corruption fixes (truncation of
details, then progress sizes, then task ids; timer alignment; rune-based
measurement) that each patched one symptom of the same structural gap:
nothing guaranteed a rendered line fits the terminal, and once a line
wraps, cursor arithmetic desyncs and the block corrupts.
Replace it with three separable units:
- tty_model.go: pure event reducer with an injected clock, preserving
first-parent-wins updates, monotonic progress and header counters
- tty_layout.go: pure (model, size, now) -> lines function; all widths
are measured in terminal cells (go-runewidth, so CJK is correct) on
plain text before coloring, and every line is clipped to the terminal
width by construction, status text included
- tty_screen.go: diff-based repaint; unchanged rows are skipped,
identical frames write nothing, a frame is a single Write; a shrinking
terminal abandons the block instead of moving the cursor over reflowed
rows
The writer coordinates them behind a mutex and stops the refresh
goroutine through context cancellation, so Done cannot block when the
operation context was cancelled first (Ctrl-C during pull). The spinner
frame is derived from the clock instead of advancing on every call, and
truncation can no longer split multi-byte runes. Visual output is
unchanged: the snapshot test reproduces the previous renderer's golden
output character for character.
Co-Authored-By: Claude Fable 5 <[email protected]>
Signed-off-by: Nicolas De Loof <[email protected]>
Compose silently ignored several spec-valid attributes it doesn't
honor outside Swarm mode: deploy.update_config, credential_spec,
ports[].mode: host, and others had no visible effect on a plain
`docker compose up`.
Detection is wired into compose-go's loader as a fail-closed
allowlist: every attribute path the schema declares, minus the
handful this runtime deliberately doesn't implement, plus a few
value-conditional checks for attributes only unsupported for one
specific value. A newly-specified attribute gets flagged
automatically, with no corresponding code change needed here.
Depends on an unreleased compose-go change; go.mod carries a
temporary replace to a fork branch until it's released.
Signed-off-by: Guillaume Lours <[email protected]>
The fake clock is only used by tests to control the debounce timer,
but requires carrying a clock abstraction through production code.
Use the standard time package for the debounce ticker and use
testing/synctest to control time in tests instead.
This removes the clock from composeService and BatchDebounceEvents,
and eliminates the clockwork dependency from the watch implementation.
Signed-off-by: Sebastiaan van Stijn <[email protected]>
full diff: https://github.com/containerd/containerd/compare/v2.3.4...v2.3.5
Security Updates
- [**CVE-2026-53495**](https://github.com/containerd/containerd/security/advisories/GHSA-7jxh-36q5-gcqv)
- [**GHSA-rp3h-jf77-q9p4**](https://github.com/containerd/containerd/security/advisories/GHSA-rp3h-jf77-q9p4)
Image Distribution
- Apply hardening to strip sensitive authentication headers when fetching descriptor URLs
Runtime
- Avoid hangs and data races when streaming container standard I/O in CRI
- Fix missing error messages in OpenTelemetry trace attributes
- Fix user and group lookup failures in container rootfs containing symlinked /etc/passwd or /etc/group
- Fix configuration loading error when drop-in configuration files have a higher version than the root configuration
- Avoid containerd startup hangs when loading shims
- Add context to error when shim delete times out
- Fix Windows Server 2022 container compatibility on host builds newer than the latest LTSC
Snapshotters
- Fix unpack failure for EROFS images containing the erofs OS feature
Signed-off-by: Sebastiaan van Stijn <[email protected]>
full diff: https://github.com/golang/crypto/compare/v0.55.0...v0.56.0
We have tagged version v0.56.0 of golang.org/x/crypto in
order to address the following security issues:
- ssh: prevent DoS on deadlocked established channel
Previously, after a channel has been established, a
malicious peer could send crafted messages that would
deadlock the entire connection.
Now, we handle all RFC 4254 channel messages; global
requests are handled explicitly. Then, treat all other
messages as a protocol error and tear the connection
down instead of buffering and blocking.
Thanks to Will Mortensen for reporting this issue.
This is CVE-2026-56855 and Go issue https://go.dev/issue/81317.
- ssh: prevent DoS on deadlocked undecided channel
Previously, a channel registered in the mux's chanList is
not usable until it is established. A malicious peer was
able flood the channel's incomingRequests, deadlocking the
entire connection.
Now, we add an atomic established state, set when a channel
becomes usable. Until such a time, handlePacket drops every
packet other than the open confirmation/failure, without
blocking and without tearing down the connection.
Thanks to Will Mortensen for reporting this issue.
This is CVE-2026-78662 and Go issue https://go.dev/issue/81316.
Signed-off-by: Sebastiaan van Stijn <[email protected]>
Building the dependency graph silently deleted unresolvable optional
depends_on references from the caller's project — and since DependsOn
is a map, even from projects sharing it. What later readers observed
depended on how many graphs had been built before them.
The pruning becomes an explicit step, applied once where the project
consumed by the engines is established — create and start — before the
graph, the dependency waits and the com.docker.compose.depends_on
label read the model, using Project.WithoutUnresolvedOptionalDependencies
introduced by compose-spec/compose-go#922 (go.mod bumped to the
post-merge commit). NewGraph now just skips the edge; required dangling
references still flow to its existing errors (naming the profiles that
would enable the dependency).
No behavior change; epic #14081, Lot 0 step 4 — precondition for a
canonical project object across plan phases.
Signed-off-by: Nicolas De Loof <[email protected]>
buildx was imported for two narrow purposes, both replaced by
docker/cli machinery compose already uses elsewhere:
- storeutil.GetProxyConfig -> configfile.ParseProxyConfig, the same
lookup docker build uses (also picks up ALL_PROXY and lowercase
variants)
- the dry-run image resolver (buildx builder + imagetools) -> a
DistributionInspect through the daemon with credentials from the CLI
config file, i.e. the same path a real pull/push would take; the
encoded-auth helper moves to internal/registry, shared with pull.go
bake is unaffected: it already execs the buildx CLI plugin. Dropping
the module also drops the transitive aws-sdk-go-v2 footprint
(-328 lines of go.sum).
Signed-off-by: Nicolas De Loof <[email protected]>
Test the upcoming buildx and BuildKit releases ahead of GA.
buildx v0.36.0-rc2 requires Go >= 1.26.3, so the go directive
moves from 1.25.9 to 1.26.3.
Signed-off-by: Guillaume Lours <[email protected]>
Rely on compose-go WithImagesResolved, which now resolves dependent
images — `type: image` volume sources and pre_start hook images —
with its already-digested guard, per-call memoization and
sibling-service detection (compose-spec/compose-go#894, #899), rather
than duplicating resolution logic CLI-side. The interpolated path gets
this for free; --no-interpolate maps the raw model onto a
pseudo-project keyed by service names to reuse the same resolution,
and --lock-image-digests keeps type:image volumes in its output.
pre_start hooks can't be carried into the lock override (hook lists
are appended on merge), so generating a lock warns that hook images
stay unpinned there.
As a side effect, `compose publish` now fails fast on unresolvable
dependent images.
Fixes#13827
Signed-off-by: Guillaume Lours <[email protected]>