Skip to content

docker context import TLS Entry Handling results in OOM #6917

@MillaFleurs

Description

@MillaFleurs

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions