CI/CD provider
Docker-in-Docker with insecure daemon configuration
Control: Pipeline must not use Docker-in-Dockerยท Config key: pipelineMustNotUseDockerInDocker
๐ What is this?
A CI/CD job uses Docker-in-Docker with an insecure daemon configuration. Setting DOCKER_TLS_CERTDIR to an empty string or using DOCKER_HOST with tcp://docker:2375 disables TLS encryption between the CI job and the Docker daemon.
โ ๏ธ Impact
Without TLS, all communication between the CI job and the Docker daemon is in plaintext. On shared infrastructure, this allows network-level eavesdropping, man-in-the-middle attacks, and Docker API command injection by other containers on the same network.
๐ง How to fix
If Docker-in-Docker is required, do not set DOCKER_TLS_CERTDIR to an empty string and use tcp://docker:2376 (TLS) instead of tcp://docker:2375 (plaintext). Prefer Kaniko or Buildah to avoid this pattern entirely.
# .gitlab-ci.yml: โ DinD with TLS disabledbuild-image: image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "" DOCKER_HOST: tcp://docker:2375 script: - docker build -t $CI_REGISTRY_IMAGE . - docker push $CI_REGISTRY_IMAGE# .gitlab-ci.yml: โ
DinD with TLS enabled (if DinD is truly required)build-image: image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "/certs" DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "/certs/client" script: - docker build -t $CI_REGISTRY_IMAGE . - docker push $CI_REGISTRY_IMAGE
# Better: use Kaniko instead of DinD entirely# (see ISSUE-412 for examples)๐ก Tips
- Port 2375 is Docker's unencrypted port. Port 2376 is the TLS-encrypted port.
- Setting
DOCKER_TLS_CERTDIR: ""explicitly disables TLS certificate generation in the DinD service. - This issue only fires when a DinD service is also present in the same job. Insecure variables without DinD are not flagged.
- The best fix is to replace Docker-in-Docker entirely with Kaniko or Buildah (see ISSUE-412).
- Only
DOCKER_TLS_CERTDIRandDOCKER_HOSTvariables declared in YAML (variables:) are checked. TLS disabled viadockerdflags inscript:or via runtime exports inbefore_script:is not detected (known limitation). - Only port 2375 is flagged as insecure. Custom non-TLS ports (e.g.,
tcp://docker:12345) are not detected.
โ๏ธ Configuration
This control is configured in .plumber.yaml under the gitlab section:
gitlab:
controls:
pipelineMustNotUseDockerInDocker:
enabled: trueSee the CLI documentation for the full configuration reference.
Docker-in-Docker with insecure daemon configuration
Control: Workflow must not use Docker-in-Dockerยท Config key: pipelineMustNotUseDockerInDocker
๐ What is this?
A workflow's DinD service is wired with TLS disabled (DOCKER_TLS_CERTDIR="", DOCKER_HOST=tcp://docker:2375).
โ ๏ธ Impact
Without TLS, the workflow talks to the Docker daemon in plaintext over the runner's internal network. Another job on the same self-hosted runner can intercept the traffic and inject Docker API commands.
๐ง How to fix
If DinD must stay, use the TLS port 2376 and let DinD generate the certs (DOCKER_TLS_CERTDIR=/certs). The better fix is to remove DinD entirely (see ISSUE-412).
# .github/workflows/image.yml: โ TLS disabledjobs: build: runs-on: [self-hosted] services: dind: image: docker:27-dind env: DOCKER_TLS_CERTDIR: "" options: --privileged env: DOCKER_HOST: tcp://docker:2375 steps: - run: docker build -t myimg .# .github/workflows/image.yml: โ
TLS enabled (or, better, no DinD)jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - run: docker build -t myimg . # uses BuildKit, no separate daemon๐ก Tips
- Port 2375 is plaintext; 2376 is TLS.
- Plumber only flags this when a
dindservice is actually present in the same job.
โ๏ธ Configuration
This control is configured in .plumber.yaml under the github section:
github:
controls:
pipelineMustNotUseDockerInDocker:
enabled: trueSee the CLI documentation for the full configuration reference.