GitHub Advisoryadvisory · Go

GHSA-xcw9-qmmf-vqxj Dozzle label filters do not restrict container event and statistics streams

MEDIUM Published 2026-09-24 Modified 2026-09-24 Official page ↗
Aliases
CVE-2026-62286
Ecosystem
Go
Packages
github.com/amir20/dozzle
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Weaknesses
CWE-200, CWE-285
Reviewed
2026-09-24

Affected packages

• Go github.com/amir20/dozzle: < 1.29.1-0.20260622172006-19c01e0fb491 → fixed in 1.29.1-0.20260622172006-19c01e0fb491

Description

Summary Dozzle supports per-user label filters in `users.yml` that are documented as an access-control boundary: "Filters are used to restrict the containers that a user can see" and "the `guest` user can only see containers with the label `com.example.app` … useful for restricting access to specific containers" (docs/guide/authentication.md). This is the mechanism operators use to give different users/tenants visibility into disjoint subsets of containers on the same host. The events stream handler `streamEvents` (GET `/api/events/stream`) honors that filter for the initial container list and for the incremental `containers-changed` updates, but it forwards two other channels — `container-stat` (live per-container CPU, memory, network and disk telemetry) and `container-event` (container lifecycle events: start/die/destroy/rename/pause/unpause, with the container's full attribute/label set) — to every authenticated client unconditionally, with no comparison against the caller's label filter. The upstream subscription `SubscribeEventsAndStats` fans out across every Docker client/host and never receives a label filter at all. As a result, any authenticated user — including one explicitly constrained to a single label scope — receives live resource telemetry for every container on every monitored host, plus lifecycle events carrying each container's name, image and complete label map. This crosses the exact isolation boundary the filter feature is documented to enforce. The leak requires no special role (it is not gated behind the shell/actions/download roles) and works on the local Docker host, so it is distinct from the previously-patched agent-path exec/attach bypass (CVE-2026-24740 / GHSA-m855-r557-5rc5) and from the exec/attach CSWSH issue (CVE-2026-44985 / GHSA-j643-x8pv-8m67). Affected code (v10.6.5) `internal/web/events.go` — `streamEvents`. The handler resolves the caller's `userLabels` and applies them to the initial list (`ListAllContainers(userLabels)`) and to the `containers-changed` increment (`ListContainersForHost(event.Host, userLabels)`), but forwards `container-stat` and the raw `container-event` with no filter check: ```go h.hostService.SubscribeEventsAndStats(r.Context(), events, stats) // no labels passed ... userLabels := h.config.Labels if h.config.Authorization.Provider != NONE { user := auth.UserFromContext(r.Context()) if user.ContainerLabels.Exists() { userLabels = user.ContainerLabels } } allContainers, errors := h.hostService.ListAllContainers(userLabels) // filtered (correct) ... case stat := data/users.yml docker run --rm amir20/dozzle:v10.6.5 generate guest --password guestpass --name Guest \ --user-filter "label=visible=yes" --user-roles all > guest.yml python3 - /dev/null || true docker run -d --name dz_visible --label visible=yes alpine \ sh -c 'while true; do echo "visible-log $(date)"; sleep 2; done' >/dev/null docker run -d --name dz_secret --label secretproject=acme-payroll alpine \ sh -c 'while true; do echo "SECRET-log $(date)"; sleep 2; done' >/dev/null 3. Start Dozzle v10.6.5 with simple auth, bound to loopback only. docker run -d --name dozzle_lab -p 127.0.0.1:8083:8080 \ -v /var/…

Related

Alias · CVE (1)

  • CVE-2026-62286 Dozzle is a realtime log viewer for docker containers. vulnerability

Weakness · CWE (2)

  • CWE-200 Exposure of Sensitive Information to an Unauthorized Actor weakness
  • CWE-285 Improper Authorization weakness

References