How to Upgrade to Docker Engine 29.9.1: Eight Security Fixes and a Test Plan
Docker Engine 29.9.0 and 29.9.1 landed within a week, bundling HTTP/2 daemon fixes and three containerd advisories. Here is how to roll them out safely.
On this page 9 sections
Docker Engine 29.9.1, released October 14, 2026, updates containerd to v2.4.2 to fix three advisories, two of which can crash containerd and one that can fill a host disk. It follows 29.9.0, which patched four HTTP/2 denial-of-service flaws in the daemon. Upgrade to 29.9.1 directly and test pulls, networking and rootless setups.
Docker Engine 29.9.1 is the kind of release that is easy to postpone and expensive to ignore. It arrived on October 14, only six days after 29.9.0, and the two releases together carry eight security fixes. Most of them let a remote party crash a service or exhaust a host resource.
This guide is for engineers who run Docker on build servers, CI runners and production hosts. It lists what each release fixed, shows a safe rollout order, and flags the changes that can surprise you. Teams that already pinned their pipelines, as in our workflow lockfile guide, will find the second half of this plan familiar. Backtrace reviews infrastructure patches by asking what breaks when you apply them.
What did Docker Engine 29.9.1 fix?
Docker Engine 29.9.1 updates containerd to v2.4.2, which closes three security issues. According to Docker's release notes for Engine 29, all three involve a crafted image or an untrusted registry.
The table below summarizes them.
| Advisory | Impact |
|---|---|
| CVE-2026-95839 | A malformed digest in a child descriptor's manifest subject annotation could crash containerd during a pull or import |
| GHSA-8647-2jxj-p2rc | A crafted Content-Length from an untrusted registry could crash containerd when parallel layer fetching was enabled |
| GHSA-hc94-p972-ch66 | Crafted images or malicious registries could exhaust host disk space, because layer data was not capped at the declared size |
None of these needs local access. They need your host to pull from a source the attacker controls or influences. That makes them most relevant to build farms, CI systems and any platform that pulls images from outside your own registry.
The release also carries ordinary bug fixes. Examples include a daemon panic with the fluentd log driver and a failure in docker ps -s when one container's size cannot be computed.
What did 29.9.0 fix a week earlier?
Release 29.9.0, dated October 8, carried the daemon-side fixes. The release notes list four HTTP/2 flaws that let a client crash the daemon or burn resources.
- CVE-2026-97032: changing the HPACK header table size during requests could crash the daemon.
- CVE-2026-78659: declaring many fields in a Trailer header could exhaust memory.
- CVE-2026-78663: resetting streams could exceed the connection-level flow control limit.
- CVE-2026-78669: repeatedly changing the initial window size could cause excessive CPU use.
A fifth item, CVE-2026-56857, applies only to Windows. A junction in the data root could cause the daemon to create directories outside it. Linux-only fleets can skip that one.
The same Go networking library update, golang.org/x/net v0.60.0, also covers the deprecated /grpc endpoint and BuildKit's frontend gRPC server. If you expose the Docker API over TCP, treat these as urgent. If the socket is local only, the exposure is smaller.
The CPU issue also appeared in a weekly package management roundup, which noted that Terraform and OpenTofu fixed the same class of problem. That is a hint of how widely the Go library flaw spread.
Should you skip 29.9.0 and go straight to 29.9.1?
Yes, go straight to 29.9.1 if your package manager offers it. Version 29.9.1 contains the 29.9.0 fixes plus the containerd update, so installing 29.9.0 first only adds a restart. Each restart on a busy host costs you a drain, a health check and a window.
The exception is a staged environment where you already validated 29.9.0. In that case, the incremental step to 29.9.1 is small and you can treat it as a patch on a known base. Do not leap two minor versions in production without a test pass.
At Backtrace, we default to the newest patch release of the line you already run. It saves restarts, and it avoids the situation where a host sits on an intermediate version that nobody is tracking.
How do you check what your hosts are running now?
Start by finding your current versions. A quick inventory beats guessing, and the commands are short. Run them on each host, or push them through your configuration tool.
docker version --format '{{.Server.Version}}'
docker info --format '{{.ServerVersion}} {{.OperatingSystem}}'
containerd --version
runc --versionRecord four things per host: the Docker Engine version, the containerd version, the runc version and whether the host runs rootless mode. The runc version matters for one fix in 29.9.1, described below.
Then sort hosts by exposure. Hosts that pull images from public registries or run builds for outside contributors come first. Hosts that only pull from your own private registry come second. An internal-only host still needs the patch, but it is not the first fire.
Finally, list any host with the API exposed on a TCP port. Those are the machines the HTTP/2 fixes from 29.9.0 protect most.
What is a safe rollout order for the upgrade?
A safe rollout moves from lowest to highest risk and checks the same things at each stage. This order has worked well for us on mixed fleets.
- Upgrade one CI runner and run a full build with a cold image cache.
- Upgrade a staging host and run your normal deploy through it.
- Upgrade a small slice of production, drained first.
- Watch pulls, restarts and disk use for a day.
- Roll the rest in batches, keeping one host on the old version as a fallback.
Drain each host before you restart the daemon. Unless you enable live restore, restarting the Docker daemon stops running containers, so plan for that. Check your own settings before assuming either behavior.
Keep the rollback path simple. Pin the package version in your configuration tool so a failed host can return to the last good build in minutes. A rollback you have never tested is a hope, not a plan.
Which changes can surprise you after upgrading?
Three changes are worth a test before you roll widely. The first is the lazy-pull default introduced in 29.9.0. It controls whether docker pull skips layers the snapshotter already provides, and it is on by default for nydus, overlaybd, soci and stargz. If you use one of those remote snapshotters, review the setting.
The second is the rootless fix in 29.9.1. The --domainname option now works with user namespaces and rootless mode, but it needs an OCI runtime that supports the domainname field, which means runc v1.2.0 or later. An older runc will not benefit from the fix.
The third is stricter validation. In 29.9.1, --link-local-ip rejects addresses outside 169.254.0.0/16 and fe80::/10. Previously such an address caused containers to fail to start. Now you get a clear error, which may reveal a bad value in an old compose file.
Firewall users should also read the networking notes. Bridge interfaces are no longer added to firewalld's docker zone when iptables and ip6tables are both disabled, and bridge networks bound to a non-docker zone now restore on daemon startup.
How do you verify the patch worked?
Verification has two parts: confirm versions, then exercise the paths the fixes touched. Start with the version commands above and confirm containerd reports v2.4.2.
Then test pulls. Pull a large multi-layer image from your registry, pull one through a mirror, and run an import from a tarball. These cover the code paths in the three containerd advisories. Watch memory and disk use during the pull.
Test networking next. Start a compose stack, confirm published ports work, and if you use encrypted overlay networks, check that nodes rejoin cleanly. Release 29.9.0 fixed several overlay problems, including encrypted traffic possibly being sent in cleartext after errors programming kernel encryption.
Finally, pair patching with scanning. A software composition scan catches vulnerable base images, while host patching covers the engine itself. You need both, because they protect different layers.
Write the result down. A one-line note with version, date and test outcome saves hours during the next audit.
How does patching fit with a busy delivery pipeline?
Patching competes with feature work, and CI capacity is the usual bottleneck. If builds already queue for an hour, a runner upgrade feels expensive. That tension is real, as we explained in our look at the CI bottleneck.
The practical fix is to schedule infrastructure patches as normal work. Put the upgrade on the board, assign an owner and give it a date. Patches that live only in someone's memory slip every time a release deadline arrives.
Automate the boring parts. Use your configuration tool to pin versions, run the inventory commands and report drift. A dashboard showing hosts behind the latest patch turns a vague worry into a number the team can reduce.
Finally, agree on a patch window with your product owners. A short weekly slot for low-risk upgrades beats emergency maintenance at midnight.
Your Docker 29.9.1 upgrade checklist
Docker Engine 29.9.1 is a worthwhile patch. It folds the 29.9.0 HTTP/2 fixes together with a containerd update that closes three pull-time advisories. The risk of waiting is highest on hosts that pull from outside your control.
Inventory your versions today, upgrade one runner, run a cold-cache build, and then widen the rollout. Check your runc version and the lazy-pull setting before you finish. Backtrace will keep covering the patches that matter for production infrastructure.