Zipkin HTTP collector gzip-expanded spans can exhaust JVM heap
Author: skadiscarletCreated Jul 1, 2026Updated Jul 1, 2026
Labelsbug
When the default Zipkin HTTP collector is anonymously exposed, a small wire-size but highly expanded gzip Zipkin v2 spans request can trigger Java heap OOM. In the 1 GiB heap, 2 GiB container retest, a roughly 3.37 MiB gzip request expanded to about 1.356 GiB and caused container exit code 3 plus sustained /health 502.
Technical Details
- Trigger shape: POST a valid Zipkin v2 JSON span list to
/api/v2/spanswithContent-Encoding: gzipto amplify decompressed size. - Root cause summary: The collector decompresses and parses the complete spans list without an effective default bound on decompressed size, span count, or gzip ratio.
- Exploitation conditions: HTTP collector is anonymously reachable, gzip is allowed, and decompressed size/span count is not limited before Zipkin decodes the body.
- Static source:
External POST /api/v2/spans or /api/v1/spans body with optional Content-Encoding: gzip - Static sink:
ZipkinHttpCollector.validateAndStoreSpans aggregates request, UnzippingBytesRequestConverter decodes gzip, Collector.acceptSpans decodes List<Span>
Suggested Remediation
- Add hard limits for request body size, object count, topic/job/key cardinality, queue length, active thread count, or aggregate retained bytes at the vulnerable entry.
- Enforce authentication and quota checks before expensive body reads, decompression, JSON/protobuf parsing, image rendering, task creation, or state retention.
- Add per-IP, per-user, per-token, or per-client rate and resource quotas for anonymous or low-privilege entries.
- Return 400/413/429 as early as possible and avoid retaining complete request bodies, payloads, or incomplete protocol state after rejection.
Recorded limits or mitigations:
- Disable external exposure of the Zipkin HTTP collector for untrusted clients.
- Reject or strictly bound gzip Content-Encoding, decompressed size, span count, per-request body size, and request rate before collector decoding.
- Ingress or Armeria request-size limits may block larger plain requests, but this 1GiB retest shows gzip decompression can reach heap pressure before an effective decompressed-size rejection.
Not affected or substantially reduced risk when:
- HTTP collector is disabled or reachable only from trusted instrumentation clients.
- Authentication, network ACLs, or gateway controls block anonymous POST /api/v2/spans.
- A front proxy or application filter enforces decompressed-size, span-count, or gzip-ratio limits before Zipkin decodes spans.
Source: openzipkin/zipkin