CI/CD provider
Docker-in-Docker service detected
Control: Pipeline must not use Docker-in-Docker · Config key: pipelineMustNotUseDockerInDocker
📋 What is this?
A CI/CD job uses a Docker-in-Docker (dind) service. On shared runners running in privileged mode, this creates a Docker daemon inside the CI container that enables container escape, lateral movement between jobs, and access to secrets from other projects on the same runner.
⚠️ Impact
Docker-in-Docker in privileged mode grants near-root access to the host. An attacker (or a compromised dependency) can escape the container, list and inspect other containers on the runner, read volumes mounted by other CI jobs (potentially containing secrets), and probe the runner's internal network.
🔧 How to fix
Replace Docker-in-Docker with a rootless container build tool. Kaniko builds container images inside a container without requiring a Docker daemon or privileged mode.
# .gitlab-ci.yml — ❌ Uses Docker-in-Docker servicebuild-image: image: docker:27 services: - docker:27-dind variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA# .gitlab-ci.yml — ✅ Uses Kaniko (no privileged mode needed)build-image: image: name: gcr.io/kaniko-project/executor:v1.23.2-debug entrypoint: [""] script: - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# .plumber.yaml# pipelineMustNotUseDockerInDocker:# enabled: true# detectInsecureDaemon: true💡 Tips
- Kaniko and Buildah are the most common alternatives to Docker-in-Docker for building container images in CI/CD.
- If Docker-in-Docker is truly required, ensure it runs on dedicated (not shared) runners with proper network isolation.
- The
detectInsecureDaemonoption (default: true) also flags jobs where TLS is disabled between the CI job and the DinD daemon. - This control inspects the
services:declaration in the CI configuration. A Docker daemon started manually fromscript:(e.g.,dockerd &) or embedded in a custom image is not detected (known limitation). - Only images with
docker:prefix and a tag containingdindorlatestare matched. Renamed or aliased DinD images (e.g.,myregistry.com/custom-builder:stable) 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 service detected
Control: Workflow must not use Docker-in-Docker · Config key: pipelineMustNotUseDockerInDocker
📋 What is this?
A workflow job declares a docker:dind service. On self-hosted runners with privileged mode enabled, this opens a container-escape path; on GitHub-hosted runners it requires the --privileged flag to actually function.
⚠️ Impact
A DinD service runs a full Docker daemon inside the job container. On shared self-hosted runners this means a compromised job can list other containers, mount their volumes, and exfiltrate secrets across jobs.
🔧 How to fix
Replace the DinD service with a rootless container builder. docker/build-push-action works without DinD by using BuildKit; Kaniko is another drop-in replacement.
# .github/workflows/image.yml — ❌ Docker-in-Docker servicejobs: build: runs-on: [self-hosted, privileged] services: dind: image: docker:27-dind options: --privileged steps: - uses: actions/checkout@v4 - run: docker build -t myimg .# .github/workflows/image.yml — ✅ BuildKit via docker/build-push-actionjobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: context: . push: false tags: myimg:${{ github.sha }}
# .plumber.yamlgithub: controls: pipelineMustNotUseDockerInDocker: enabled: true💡 Tips
- If DinD is unavoidable (rare on GitHub-hosted runners), use Kaniko or Buildah instead — both run rootless.
- Pair with ISSUE-413 to catch insecure daemon configuration when DinD is actually present.
⚙️ 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.