Docker label value used unescaped to build docker-compose commands (argument injection on shared hosts)

Author: carfeiiCreated Aug 4, 2026Updated Aug 4, 2026

Summary

lazydocker reads a container's com.docker.compose.project label directly (pkg/commands/docker.go, container-to-service mapping) and, via a project-name auto-detection heuristic in RefreshContainersAndServices, can adopt that label's value from any container on the host, not only containers belonging to the current user's project, as long as the container's com.docker.compose.service label matches a service name already defined in the local docker-compose.yml. That value is then concatenated unescaped (fmt.Sprintf("%s -p %s", ...) in NewCommandObject) into the docker-compose command prefix used to build every subsequent command for that service.

A plain docker run --label invocation accepts an arbitrary string for this label, with no character restriction (unlike a docker-compose-parsed project name, which is restricted to a safe character class by the Compose spec). This lets a local user on a shared Docker host create one container with a crafted label to inject extra command-line arguments into another user's lazydocker-issued docker-compose commands, requiring only that the attacker's chosen service-name label matches a service name the victim already uses (common names like "web" or "app" make this easy).

Validated against v0.25.2.

POC

(available upon request)

Impact

On a shared or multi-tenant Docker host, any user who can create a container (no special privileges, no docker-compose required) can inject arbitrary extra flags into another user's lazydocker-issued docker-compose commands for a matching service name, causing those commands to silently fail against the victim's own service. Depending on the injected flag, this could extend beyond denial of service, for example toward causing docker-compose to merge in an attacker-supplied compose file on a subsequent up/recreate.

Suggested Fix

Validate any label-derived value against the character class docker-compose itself requires for a project name before using it to build a command line, and prefer the compose-file-derived project name over a label match when both are available, rather than adopting the first matching label found across the whole host.

Source: jesseduffield/lazydocker