`docker context import` TLS Entry Handling results in OOM
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.1k
- Forks
- 2.2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 43
Description
Description
docker context import handles zip archives where the meta.json branch
correctly limits decompressed reads with limitedReader (10MB cap), but the
tls/ branch uses a bare io.ReadAll(f) with no size limit. Since the raw zip
file is limited to 10MB compressed, but zip compression can achieve 1000:1+
ratios on repetitive data, a crafted zip can contain a TLS entry that
decompresses to gigabytes, crashing the Docker CLI with OOM.
There is inconsistency between two branches in the same function:
// store.go:457-467 — metaFile branch: PROTECTED
if zf.Name == metaFile {
f, err := zf.Open()
// ...
data, err := io.ReadAll(&limitedReader{R: f, N: maxAllowedFileSizeToImport}) // <-- 10MB cap
// ...
// store.go:476-486 — tls/ branch: UNPROTECTED
} else if strings.HasPrefix(zf.Name, "tls/") {
f, err := zf.Open()
// ...
data, err := io.ReadAll(f) // <-- no cap; decompresses to arbitrary size
// ...
}
Reproduce
# zeros compress at ~1000:1 with deflate
zf.writestr('tls/docker/ca.pem', b'\x00' * BOMB_SIZE)
import os
compressed_size = os.path.getsize(OUTPUT)
print(f"Compressed zip size: {compressed_size / 1024:.1f} KB")
print(f"Decompression ratio: {BOMB_SIZE / compressed_size:.0f}:1")
print(f"Output: {OUTPUT}")
print()
print("Run: docker context import bomb-test /tmp/context-bomb.zip")
### Run the POC
```bash
# Generate the bomb
python3 /tmp/generate-bomb.py
# Verify compressed size is well under 10MB
ls -lh /tmp/context-bomb.zip
# Expected: ~500KB-1MB
# Trigger the bug (WARNING: will allocate ~500MB of memory)
docker context import bomb-test /tmp/context-bomb.zip
Expected behavior
There should be checks on size on both branches.
docker version
lient: Docker Engine - Community
Version: 29.3.1
API version: 1.53 (downgraded from 1.54)
Go version: go1.26.1
Git commit: c2be9ccfc3
Built: Wed Mar 25 14:22:32 2026
OS/Arch: darwin/arm64
Context: desktop-linux
Server: Docker Desktop 4.65.0 (221669)
Engine:
Version: 29.2.1
API version: 1.53 (minimum version 1.44)
Go version: go1.25.6
Git commit: 6bc6209
Built: Mon Feb 2 17:16:47 2026
OS/Arch: linux/arm64
Experimental: false
containerd:
Version: v2.2.1
GitCommit: dea7da592f5d1d2b7755e3a161be07f43fad8f75
runc:
Version: 1.3.4
GitCommit: v1.3.4-0-gd6d73eb8
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker info
docker info
Client: Docker Engine - Community
Version: 29.3.1
Context: desktop-linux
Debug Mode: false
Plugins:
agent: create or run AI agents (Docker Inc.)
Version: v1.29.0
Path: /Users/daniel/.docker/cli-plugins/docker-agent
ai: Docker AI Agent - Ask Gordon (Docker Inc.)
Version: v1.19.0
Path: /Users/daniel/.docker/cli-plugins/docker-ai
buildx: Docker Buildx (Docker Inc.)
Version: v0.32.1-desktop.1
Path: /Users/daniel/.docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v5.1.0
Path: /Users/daniel/.docker/cli-plugins/docker-compose
debug: Get a shell into any image or container (Docker Inc.)
Version: 0.0.47
Path: /Users/daniel/.docker/cli-plugins/docker-debug
desktop: Docker Desktop commands (Docker Inc.)
Version: v0.3.0
Path: /Users/daniel/.docker/cli-plugins/docker-desktop
dhi: CLI for managing Docker Hardened Images (Docker Inc.)
Version: v0.0.0-alpha
Path: /Users/daniel/.docker/cli-plugins/docker-dhi
extension: Manages Docker extensions (Docker Inc.)
Version: v0.2.31
Path: /Users/daniel/.docker/cli-plugins/docker-extension
init: Creates Docker-related starter files for your project (Docker Inc.)
Version: v1.4.0
Path: /Users/daniel/.docker/cli-plugins/docker-init
mcp: Docker MCP Plugin (Docker Inc.)
Version: v0.40.1
Path: /Users/daniel/.docker/cli-plugins/docker-mcp
model: Docker Model Runner (Docker Inc.)
Version: v1.1.5
Path: /Users/daniel/.docker/cli-plugins/docker-model
offload: Docker Offload (Docker Inc.)
Version: v0.5.70
Path: /Users/daniel/.docker/cli-plugins/docker-offload
pass: Docker Pass Secrets Manager Plugin (beta) (Docker Inc.)
Version: v0.0.24
Path: /Users/daniel/.docker/cli-plugins/docker-pass
sandbox: Docker Sandbox (Docker Inc.)
Version: v0.12.0
Path: /Users/daniel/.docker/cli-plugins/docker-sandbox
sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
Version: 0.6.0
Path: /Users/daniel/.docker/cli-plugins/docker-sbom
scout: Docker Scout (Docker Inc.)
Version: v1.20.1
Path: /Users/daniel/.docker/cli-plugins/docker-scout
Server:
Containers: 8
Running: 2
Paused: 0
Stopped: 6
Images: 3
Server Version: 29.2.1
Storage Driver: overlayfs
driver-type: io.containerd.snapshotter.v1
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
CDI spec directories:
/etc/cdi
/var/run/cdi
Discovered Devices:
cdi: docker.com/gpu=webgpu
Swarm: active
NodeID: ofx411xzsjxecd11xami0kk4d
Is Manager: true
ClusterID: q326fzbjro7hy14dsad1u9k7q
Managers: 1
Nodes: 1
Data Path Port: 4789
Orchestration:
Task History Retention Limit: 5
Raft:
Snapshot Interval: 10000
Number of Old Snapshots to Retain: 0
Heartbeat Tick: 1
Election Tick: 10
Dispatcher:
Heartbeat Period: 5 seconds
CA Configuration:
Expiry Duration: 3 months
Force Rotate: 0
Autolock Managers: false
Root Rotation In Progress: false
Node Address: 192.168.65.3
Manager Addresses:
192.168.65.3:2377
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: dea7da592f5d1d2b7755e3a161be07f43fad8f75
runc version: v1.3.4-0-gd6d73eb8
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.12.76-linuxkit
Operating System: Docker Desktop
OSType: linux
Architecture: aarch64
CPUs: 8
Total Memory: 7.653GiB
Name: docker-desktop
ID: 4413ecca-8450-43ca-bca2-80d61e5f6784
Docker Root Dir: /var/lib/docker
Debug Mode: false
HTTP Proxy: http.docker.internal:3128
HTTPS Proxy: http.docker.internal:3128
No Proxy: hubproxy.docker.internal
Labels:
com.docker.desktop.address=unix:///Users/daniel/Library/Containers/com.docker.docker/Data/docker-cli.sock
Experimental: false
Insecure Registries:
hubproxy.docker.internal:5555
127.0.0.0/8
::1/128
Live Restore Enabled: false
Firewall Backend: iptables
Additional Info
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in store.go around the metaFile and tls/ branches of docker context import, and compare how each opened archive entry is read. Run the provided Python bomb generator and docker context import command to reproduce the excessive allocation. Done means TLS entries are subject to the same 10MB decompressed-read protection as meta.json and the reproduction no longer causes unbounded allocation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100