Rules / GL054
GL054 Docker-in-Docker service implies a privileged runner
Severity: warn
OWASP: CICD-SEC-7 – Insecure System Configuration
CWE: CWE-250 – Execution with Unnecessary Privileges
Risk
Using docker:dind as a service requires the GitLab Runner to be configured with privileged = true in its config.toml. A privileged runner grants the job full root access to the host kernel — container isolation is effectively removed. Any compromised dependency, injected script, or malicious image running in that job can escape the container and access the runner host, other jobs' secrets, or the broader network.
privileged: true cannot be set in .gitlab-ci.yml itself, but the presence of a docker:dind service is a reliable indicator that the runner must be privileged. This makes DinD usage the detectable proxy for a privileged-runner requirement.
Trigger example
build-image:
services:
- docker:26.0-dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
script:
- docker build -t myapp .
- docker push myapp
The rule also flags a DOCKER_HOST: tcp://docker:2375 (or :2376) variable on its own, since it points at a DinD daemon even when the service is declared elsewhere.
Safe alternatives
Kaniko (runs as non-root, no Docker daemon):
build-image:
image:
name: gcr.io/kaniko-project/executor:v1.21.0-debug
entrypoint: [""]
script:
- /kaniko/executor --context $CI_PROJECT_DIR --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
Buildah (rootless builds):
build-image:
image: quay.io/buildah/stable:v1.35.0
script:
- buildah bud -t myapp .
- buildah push myapp
GitLab-managed Docker socket binding (uses the runner host's Docker socket — reduces isolation but avoids full privileged mode):
build-image:
image: docker:26.0
variables:
DOCKER_HOST: unix:///var/run/docker.sock
script:
- docker build -t myapp .
Notes
- Severity is
warn— DinD is a legitimate pattern in some environments, but should always be a deliberate, documented choice. - GL031 covers the related
DOCKER_TLS_CERTDIR: ""misconfiguration (TLS disabled on the DinD daemon); GL054 covers the broader DinD usage pattern regardless of TLS configuration. - The fix is not always to remove DinD — it is to make the privileged-runner requirement explicit and to consider rootless alternatives.
- Suppress per-file with
.glsec-ignoreor inline# glsec:ignore GL054when DinD is a justified, documented requirement.
Documentation for glsec 1.23.0. Source of this page · Rule implementation